说明

工厂模式是我们最常用的实例化对象模式,使用工厂方法代替new操作的一种模式,使用工厂模式,可能多做一些工作,但可以给你系统带来更大的可扩展性和尽量少的修改量。

简单工厂模式

模式说明

简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。

简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。

Factory模式

简单工厂的编程模式一般为:

Creator::FactoryMethod(String product) {
    if (product == "A") {
        createA();
    } else if (product == "B") {
        createB();
    } else if ... {
        ......
    }
}

简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

使用场景

  • 工厂类负责创建的对象比较少;
  • 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;

缺点分析

简单工厂模式的缺点在于工厂类的任务太重,且不符合面向对象编程思想中的“开闭原则”,新增一种产品时就需要修改对象工厂类。

JDK示例

代替构造函数创建对象,方法名比构造函数清晰
如Integer.valueOf,Class.forName等方法

工厂方法模式

模式说明

为了克服上面的简单工厂方法的种种弊端,工厂方法模式将工厂也进行了抽象,工厂接口定义生产的产品接口,而具体工厂类则实现接口创建特定产品。

其UML图如下:

Factory模式

使用者在初始化时根据自己需求创建特定的ConcreteCreator,接下来所有的都是面向接口编程。

JDK示例

Factory模式

这里的Iterable是工厂接口,而ArrayList、LinkedList则是具体的实现工厂类,工厂生产的产品是Itrator。

抽象工厂方法

问题背景

上面的工厂方法确实是好,但是它为每个产品都需要定义一个工厂接口,在某些情况下会显得很臃肿,例如:

A公司欲开发一套界面皮肤库,可以对Java桌面软件进行界面美化。为了保护版权,该皮肤库源代码不打算公开,而只向用户提供已打包为jar文件的class字节码文件。用户在使用时可以通过菜单来选择皮肤,不同的皮肤将提供视觉效果不同的按钮、文本框、组合框等界面元素,其结构示意图如图1所示:

Factory模式

该皮肤库需要具备良好的灵活性和可扩展性,用户可以自由选择不同的皮肤,开发人员可以在不修改既有代码的基础上增加新的皮肤。

如果采用工厂方法模式来编码,设计出来的类图应该是下面这样:

Factory模式

此方案存在以下问题:

  • 当需要增加新的皮肤时,虽然不要修改现有代码,但是需要增加大量类,针对每一个新增具体组件都需要增加一个具体工厂,类的个数成对增加,这无疑会导致系统越来越庞大,增加系统的维护成本和运行开销;
  • 由于同一种风格的具体界面组件通常要一起显示,因此需要为每个组件都选择一个具体工厂,用户在使用时必须逐个进行设置,如果某个具体工厂选择失误将会导致界面显示混乱,虽然我们可以适当增加一些约束语句,但客户端代码和配置文件都较为复杂。

模式说明

在工厂方法模式中具体工厂负责生产具体的产品。一般情况下,一个具体工厂中只有一个或者一组重载的工厂方法。但是有时候我们希望一个工厂可以提供多个产品对象,而不是单一的产品对象,如一个电器工厂,它可以生产电视机、电冰箱、空调等多种电器,而不是只生产某一种电器。为了更好地理解抽象工厂模式,我们先引入两个概念:

  • 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
  • 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。

Factory模式

在上图中,不同颜色的多个正方形、圆形和椭圆形分别构成了三个不同的产品等级结构,而相同颜色的正方形、圆形和椭圆形构成了一个产品族,每一个形状对象都位于某个产品族,并属于某个产品等级结构。上中一共有五个产品族,分属于三个不同的产品等级结构。我们只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一确定这个产品。

当系统所提供的工厂生产的具体产品并不是一个简单的对象(如上面的皮肤库),而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式。抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形式。

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率。抽象工厂模式示意图如下所示:

Factory模式

JDK示例

Factory模式

在这里,Connection作为一个工厂接口,内部定义了各种Statement的创建接口,而具体的数据库引擎分别实现这些接口。这样,一个Connection接口便定义了多种产品(Statement)的创建接口。

参考