定义
工厂模式:定义创建对象的接口,让子类决定实例化哪一个类,工厂方法使得一个类的实例化延迟到其子类。
使用场景
下列情况会适合使用工厂模式:
- 编译时无法准确与其要创建的对象类
- 类想让其子类决定在运行时创建什么
- 类有若干个辅助类为其子类,而你想将返回某个子类这一信息局部化
在Cocoa Touch框架中,NSNumber就是典型的工厂方法构造。NSNumber通过类方法numberWithBool:接口实例化NSCFBoolean实例,将bool值参数传递给实例化对象。
类图结构
工厂方法模式的类结构图如下:
代码实现
下面我们来用代码实现下工厂模式。
需求如下:实现一个画布页面背景,根据用户操作或者默认行为生成不同的背景图,背景图类型样式会随着需求不断的新增。
实现如下:
@interface XQCanvasView : UIView
- (instancetype)initWithFrame:(CGRect)frame;
@end
XQCanvasView是背景图的父类,定义一个创建接口initWithFrame
@interface XQPaperCanvasView : XQCanvasView
@end
@implementation XQPaperCanvasView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
UIImageView *imageView = [UIImageView new];
imageView.image = [UIImage imageNamed:@"paper.jpg"];
imageView.frame = frame;
[self addSubview:imageView];
}
return self;
}
@end
XQPaperCanvasView实现父类的创建接口initWithFrame,增加纸纹理的背景
@interface XQClothCanvasView : XQCanvasView
@end
@implementation XQClothCanvasView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
UIImageView *imageView = [UIImageView new];
imageView.image = [UIImage imageNamed:@"cloth.jpg"];
imageView.frame = frame;
[self addSubview:imageView];
}
return self;
}
@end
XQClothCanvasView实现父类创建接口,增加布纹理的背景
@interface XQCanvasViewGenerator : NSObject
- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame;
@end
@implementation XQCanvasViewGenerator
- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame{
return [[XQCanvasView alloc] initWithFrame:frame];
}
@end
XQCanvasViewGenerator为生产者的父类,定义一个创建画布背景图XQCanvasView的接口。默认实现返回一个空白的XQCanvasView
@interface XQPaperCanvasViewGenerator : XQCanvasViewGenerator
@end
@implementation XQPaperCanvasViewGenerator
- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame{
return [[XQPaperCanvasView alloc] initWithFrame:frame];
}
@end
XQPaperCanvasViewGenerator实现父类的canvasViewWithFrame工厂方法,生成XQPaperCanvasView的纸纹理背景对象。
@interface XQClothCanvasViewGenerator : XQCanvasViewGenerator
@end
@implementation XQClothCanvasViewGenerator
- (XQCanvasView *)canvasViewWithFrame:(CGRect)frame{
return [[XQClothCanvasView alloc] initWithFrame:frame];
}
@end
XQClothCanvasViewGenerator实现父类的canvasViewWithFrame工厂方法,生成XQClothCanvasView的布纹理背景对象。
上面就是所有工厂方法涉及的类,下面看使用:
@interface XQCanvasViewController : UIViewController
- (void)loadCanvasViewWithGenerator:(XQCanvasViewGenerator *)generator;
@end
@interface XQCanvasViewController ()
@property (nonatomic, strong)XQCanvasView *canvasView;
@end
@implementation XQCanvasViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self loadCanvasViewWithGenerator:[XQClothCanvasViewGenerator new]];
}
- (void)loadCanvasViewWithGenerator:(XQCanvasViewGenerator *)generator{
[self.canvasView removeFromSuperview];
XQCanvasView *aCanvas = [generator canvasViewWithFrame:self.view.bounds];
self.canvasView = aCanvas;
[self.view addSubview:aCanvas];
}
@end
画布视图控制器XQCanvasViewController定义了一个加载背景图的方法loadCanvasViewWithGenerator,供外部调用配置不同的背景图。在viewDidLoad中,调用[self loadCanvasViewWithGenerator:[XQClothCanvasViewGenerator new]];生成默认的布纹理背景图。loadCanvasViewWithGenerator方法实现中,先移除上一次的背景图self.canvasView,然后再用生成器generator生成对应的不同背景图。
当需求新增其他类型复杂的背景图时,只需新增对应的XQCanvasView背景图子类,与其对应的XQCanvasViewGenerator生成器子类,在调用的地方传递新生成的XQCanvasViewGenerator生成器子类即可。
总结
工厂方法是在面向对象软件设计中应用非常普遍的设计模式。工厂方法从代码中消除了对应用特有类的耦合,只需处理产品Product的抽象接口即可。