思考并回答以下问题:
- 抽象工厂模式的官方定义是什么?
- 抽象工厂比工厂模式有什么区别?
本章涵盖:
- 抽象工厂模式的定义
- 抽象工厂模式的实现
- 可应用抽象工厂模式的场合
抽象工厂模式的定义
抽象工厂模式是工厂方法模式(Factory Method)的高级版,在介绍抽象工厂模式之前,让我们先来回顾工厂方法模式的定义与结构图。
工厂方法模式的定义
工厂方法模式(Factory Method)在GoF中的定义是:1
定义一个可以产生对象的接口,但是让子类决定要产生哪一个类的对象。工厂方法模式让类的实例化程序延迟到子类中实行。
也就是,定义一个可以产生对象的接口,让子类决定要产生哪一个类的对象,其结构图如图1所示。
图1 工厂方法模式的结构图
抽象工厂模式的定义
抽象工厂模式(Abstract Factory)在GoF中的定义是:1
提供一个能够建立整个类群组或有关联的对象,而不必指明它们的具体类。
抽象工厂模式的结构图如图2所示。
图2 抽象工厂模式的结构图
抽象工厂模式的应用方式是:系统中先定义一组抽象类(AbstractProductA、AbstractProductB),而这些抽象类的子类,是根据不同的执行环境去产生的,所以:
- ProductA1和ProductB1是给执行环境1时使用的。
- ProductA2和ProductB2是给执行环境2时使用的。
现在,系统如果要能根据当前的执行环境,自动决定要产生哪一组子类时,抽象工厂模式就可以派上用场。抽象工厂接口定义了产生不同类对象的方法(CreateProductA、CreateProductB),而继承的工厂子类,则是实现产生不同产品的类:
- ConcreteFactory1是给执行环境1时使用的,可以产生ProductA1和ProductB1。
- ConcreteFactory2是给执行环境2时使用的,可以产生ProductA2和ProductB2。
抽象工厂模式的实现
就上述结构图来说,以下是抽象工厂模式的范例程序:
Listing1 实现抽象工厂(AbstractFactory.cs)
1 | // 可生成各抽象成品对象的操作 |
测试程序如下:
Listing2 测试抽象工厂(AbstractFactoryTest.cs)
1 | void UnitTest() |
使用不同的子工厂类就可以产生对应的ProductA和ProductB:
执行结果
1 | 生成对象类型A1 |
可应用抽象工厂模式的场合
在Unity3D的界面设计-组合模式中,我们使用Unity3D内置的UI系统——UGUI用于开发玩家界面。而早在Unity3D发布UGUI系统之前,坊间就有不少Unity3D插件让游戏开发者使用如NGUI、iGUI等。在面对这么多样的工具可以选择之下,开发者最好能提供一个方便的架构让这些工具能快速转换使用。
设计上,我们可以先将每一个界面组件都设计为一个抽象类,如显示文字的ILabel、显示图片的IImage、提供选项的ICheckBox…,并在每个抽象类中定义共同的操作方法;然后针对每一个界面工具继承对应的子类,如针对NGUI工具的NGUILable、NGUImage…,针对iGUI定义的iGUILabel、iGUIImage等;最后,再针对不同群组的界面组件也实现出能产生它们的工厂,如能产生NGUI组件的NGUIFactory,能产生iGUI的iGUIFactory。
在这样的设计架构下,游戏开发者就能根据不同的需求来选择要使用的界面工具。虽然界面组件的设计摆放上需要使用对应工具,但是在程序设计上,只需要提供不同的界面工厂,就能将界面组件整个转换到不同的工具上。
当然,随着开发工具的演进,会有更多更新的界面开发工具出现。那时只要针对新的开发工具,继承实现新的界面组件及工厂类,就能马上让游戏快速转换到新的开发工具中。而这也是抽象工厂模式的优点:能将产生的对象“整组”转换到不同的类群组上。