开篇
在这篇文章中我们讲下工厂方法和抽象工厂这两种设计模式。几乎在每个面向对象的程序里都会看到工厂方法,随便让一个程序员或者软院,计科的学生说个设计模式都会说出工厂模式。看似普通的东西其实并不普通,今天我们就来认真的研究下什么是工厂方法,它和抽象工厂有什么异同?抽丝剥茧,总结一套心得,在以后写程序的时候更得心应手,不会心存疑虑。
工厂方法
总的来说,工厂方法是抽象工厂的组成部分,各种具体工厂类重载抽象工厂类中的方法,并用这些工厂方法创建具体产品。工厂方法的精髓在于: 一个类无法预期要生成那个类的对象,需要其子类来指定要生成的对象。
下图是工厂方法模式的静态类图(图片来源于《编程之道》)
Creator是一个抽象的工厂父类,定义了FactoryMethod这个需要重载的工厂方法,其子类ConcreteCreator实现了这个方法,返回具体的产品。在1994年Wesley最初定义工厂模式的时候,他说: 工厂方法模式,就是让子类决定实例化哪个类,使得一个类的实例化延迟到其子类。在平时的coding中,我们也会经常遇到这样的情况,例如你从网络请求一些产品的列表,但是产品种类很多,需要运行时才能确定,这时候就需要使用工厂方法,例如[[self class] xxxFactory]来让具体子类生成产品。
何时使用工厂方法以及它的好处
以下情形会让你自然而然的想到使用工厂方法:
- 编译时无法确定要创建对象的类
- 想让子类决定运行时创建什么
- 局部化信息。例如一个类有若干子类为其辅助类,而你想返回具体的子类的信息
工厂方法可以让创建出来的产品有一组共同的行为,而且客户端无需修改任何代码就可以拥有不同的产品,当你想加入新产品的时候,只需增加一个子类,无需修改客户端代码。
Demo
我们现在要生成两种画布,一个是ClothCanvasView(布质风格)另一个是PaperCanvasView(纸质风格)。我们将创建一个抽象的generator来生成这些画布。
如上图,CanvasViewGenerator是一个基类,包含一个工厂方法canvasViewWithFrame,其两个子类负责实现和返回具体的CanvasView.
CanvasViewGenerator的代码:
#import "CanvasViewGenerator.h"
@implementation CanvasViewGenerator
- (void)canvasViewWithFrame:(CGRect)aFrame
{
return [[CanvasView alloc] initWithFrame:aFrame];
}
这里面只是返回无图案的CanvasView,具体的view需要子类来返回。
PaperCanvasViewGenerator的代码:
#import "PaperCanvasViewGenerator.h"
@implementation PaperCanvasViewGenerator
- (void)canvasViewWithFrame:(CGRect)aFrame
{
return [[PaperCanvasView alloc] initWithFrame:aFrame];
}
ClothCanvasViewGenerator的代码:
#import "ClothCanvasViewGenerator.h"
@implementation ClothCanvasViewGenerator
- (void)canvasViewWithFrame:(CGRect)aFrame
{
return [[ClothCanvasView alloc] initWithFrame:aFrame];
}
当使用画布的时候,只需在CanvasViewController里面调用 [generator canvasViewWithFrame:aFrame]即可,generator类型是基类类型。
工厂方法就是这些了,它的应用非常普遍,很好地封装了工厂子类,并与客户端类解耦。下一篇介绍抽象工厂,以及和工厂方法的对比。