从JDK中学习设计模式——工厂方法模式

782 阅读3分钟

这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

概述

工厂方法模式(Factory Method Pattern)属于创建型模式,其具体工厂利用了多态的特性,因此又被称为多态工厂模式(Polymorphism Factory Pattern)

工厂方法模式就是当有多个工厂时,每个工厂创建它所对应的实例。例如:张三不但开了一家水壶制造厂,还开了一家斧头制造厂,当客户需要某种产品时,只需要找到对应的制造厂就可以了,而不需要知道具体的产品,也不需要知道产品是如何生产的。制造厂就是抽象工厂(Factory),水壶制造厂和斧头制造厂就是具体的工厂(ConcreteFactory),水壶制造厂生产出来的水壶就是具体的产品(ConcreteProduct)。

结构

工厂方法模式UML.png

  • Factory:抽象工厂类,在 Java 中为接口或抽象类,是所有具体工厂的父类,该类供外部直接调用。
  • ConcreteFactory:具体工厂类,负责创建对应的具体产品,一个具体工厂对应一个具体的产品。需要实现抽象工厂类所定义的抽象方法。
  • Product:抽象产品类,在 Java 中为接口或抽象类,是所有具体产品的父类,用于描述具体产品的共有属性。
  • ConcreteProduct:具体产品类,它是具体工厂类所要创建的目标,需要实现抽象产品类所定义的抽象方法。

优点

  1. 符合开闭原则,扩展性和可维护性强。当需要扩展时,只需要添加一个工厂实例(ConcreteFactory)即可,而无需修改原有的工厂实例。解决了简单工厂模式中对修改开放的问题。
  2. 工厂类使用了依赖倒置原则,依赖抽象而不是具体,实现了使用(客户)和实现(具体类)的松耦合。
  3. 满足了迪米特法则,客户只需要知道所需产品的具体工厂,而无须知道具体工厂创建产品的过程,甚至不需要知道具体产品的类名。
  4. 通过具体工厂来创建产品,而不是参数,使该模式下的程序更健壮,更方便维护。

缺点

  1. 一个具体产品对应一个具体产品类和具体工厂类,当具体产品过多时会使系统类的数目过多,增加系统的复杂度。
  2. 简单工厂模式,增加功能仅需修改工厂类;工厂方法模式,增加功能需要修改客户端。

应用场景

  1. 客户端只需要知道创建产品的具体工厂,而不需要知道该产品所对应的产品类。
  2. 具体产品类的数目不确定,随时有新的子类增加进来,或者是不确定将来需要哪些具体产品。
  3. 定义一个创建对象的接口,由子类决定要实例化哪一个类;客户端可以动态地指定工厂类所创建的具体产品。

JDK 中的应用

JDK 中有很多地方使用了工厂方法模式,如:java.util.Collection#iterator() 。对于 iterator() 方法来说 Collection 接口就是一个根抽象工厂,下面还有 List 等接口作为抽象工厂,再往下有 ArrayList 等具体工厂。java.util.Iterator 接口是根抽象产品,下面有 ListIterator 等抽象产品,还有 ArrayListIterator 等作为具体的产品。简化后的 UML 图如下:

JDK简化的工厂方法模式.png

此外还有如下源码中使用了工厂方法模式:

  • java.lang.Proxy#newProxyInstance()
  • java.lang.Object#toString()
  • java.lang.Class#newInstance()
  • java.lang.reflect.Array#newInstance()
  • java.lang.reflect.Constructor#newInstance()
  • java.lang.Boolean#valueOf(String)
  • java.lang.Class#forName()