生產(chǎn)者自身不必是抽象工廠网棍,它可以是任何類。
要點(diǎn)在于
1.不是直接創(chuàng)建對(duì)象妇智,
2.而是使用類或?qū)ο蟮墓S方法創(chuàng)建具體產(chǎn)品滥玷,
3.并以抽象類型返回氏身。
工廠方法模式是抽象工廠模式的組成部分。各種具體工廠重載其抽象工廠父類中定義的工廠方法惑畴,并用這個(gè)重載的工廠方法創(chuàng)建自己的產(chǎn)品(對(duì)象)蛋欣。
4.1 何為工廠方法模式
工廠方法也稱為虛構(gòu)造器(virtual constructor)。
他適用于這種情況:一個(gè)類無法預(yù)期需要生成哪個(gè)類的對(duì)象桨菜,想讓其子類來指定所生成的對(duì)象豁状。
工廠方法模式的靜態(tài)類結(jié)構(gòu)如圖4-1所示。
說明:
1. 抽象的Product(產(chǎn)品)定義了工廠方法創(chuàng)建的對(duì)象的接口倒得。
2. ConcreteProduct實(shí)現(xiàn)了Product接口。
3. Creator定義了返回Product對(duì)象的工廠方法夭禽。它也可以為工廠方法定義一個(gè)默認(rèn)實(shí)現(xiàn)霞掺,返回默認(rèn)ConcreteProduct對(duì)象。Creator的其他操作可以調(diào)用此工廠方法創(chuàng)建Product對(duì)象讹躯。
4. ConcreateCreator是Creator的子類菩彬。它重載了工廠方法,以返回ConcreteProduct的實(shí)例潮梯。
工廠方法模式:定義創(chuàng)建對(duì)象的接口骗灶,讓子類決定實(shí)例化哪一個(gè)類。工廠方法使得一個(gè)類的實(shí)例化延遲到其子類秉馏。
工廠方法
1.通過類繼承創(chuàng)建抽象產(chǎn)品耙旦。
2.創(chuàng)建一種產(chǎn)品。
3.子類化創(chuàng)建者并重載工廠方法以創(chuàng)建新產(chǎn)品萝究。
4.2 何時(shí)使用工廠方法
- 編譯時(shí)無法準(zhǔn)確預(yù)期要?jiǎng)?chuàng)建的對(duì)象的類免都;
- 類想讓其子類決定在運(yùn)行時(shí)創(chuàng)建什么;
- 類由若干輔助類為其子類帆竹,而你想將返回哪個(gè)字累這一信息局部化绕娘。
使用這一模式的最低限度是:工廠方法能給予類在變更返回哪一種對(duì)象這一點(diǎn)上更多的靈活性。
4.3 為何這是創(chuàng)建對(duì)象的安全方法
工廠方法模式讓客戶程序可以要求由工廠方法創(chuàng)建的對(duì)象擁有一組共同的行為栽连。所以往類層次結(jié)構(gòu)中引入新的具體產(chǎn)品并不需要修改客戶端代碼险领,因?yàn)榉祷氐娜魏尉唧w對(duì)象的接口都跟客戶端一直在用的從前的接口相同。
4.4 在TouchPainter中生成不同畫布
4.1 畫布類
CanvasView:畫布類
//CanvasView.h
@interface CanvasView : UIView
@end
//CanvasView.m
@implementation CanvasView
@end
ClothCanvasView:有布質(zhì)風(fēng)格的背景
//ClothCanvasView.h
#import "CanvasView.h"
@interface ClothCanvasView : CanvasView
{
// 一些私有變量
}
// 其他一些特定行為
@end
//ClothCanvasView.m
@implementation ClothCanvasView
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 在上面添加一個(gè)紙圖像視圖作為畫布背景
UIImage *backgroundImage = [UIImage imageNamed:@"cloth"];
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:backgroundImage];
[self addSubview:backgroundView];
}
return self;
}
// 其他行為的實(shí)現(xiàn)
@end
PaperCanvasView:有再生紙風(fēng)格的背景
//.h
#import "CanvasView.h"
@interface PaperCanvasView : CanvasView
{
// 一些私有變量
}
// 其他一些特定行為
@end
//PaperCanvasView.m
@implementation PaperCanvasView
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 在上面添加一個(gè)紙圖像視圖作為畫布背景
UIImage *backgroundImage = [UIImage imageNamed:@"paper"];
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:backgroundImage];
[self addSubview:backgroundView];
}
return self;
}
// 其他行為的實(shí)現(xiàn)
@end
4.2 生成器類
為定義好的產(chǎn)品各自定義一個(gè)生成器秒紧。
CanvasViewGenerator:默認(rèn)畫布的生成器
//CanvasViewGenerator.h
#import "CanvasView.h"
@interface CanvasViewGenerator : NSObject
{
}
- (CanvasView *)canvasViewWithFrame:(CGRect)aFrame;
@end
//CanvasViewGenerator.m
@implementation CanvasViewGenerator
-(CanvasView *)canvasViewWithFrame:(CGRect)aFrame
{
return [[CanvasView alloc] initWithFrame:aFrame];
}
@end
PaperCanvasViewGenerator:紙風(fēng)格畫布的生成器
//PaperCanvasViewGenerator.h
#import "PaperCanvasView.h"
@interface PaperCanvasViewGenerator : CanvasViewGenerator
{
}
-(CanvasView *)canvasViewWithFrame:(CGRect)aFrame;
@end
//PaperCanvasViewGenerator.m
@implementation PaperCanvasViewGenerator
-(CanvasView *)canvasViewWithFrame:(CGRect)aFrame
{
return [[PaperCanvasView alloc] initWithFrame:aFrame];
}
@end
ClothCanvasViewGenerator:布風(fēng)格畫布的生成器
//ClothCanvasViewGenerator.h
#import "CanvasViewGenerator.h"
@interface ClothCanvasViewGenerator : CanvasViewGenerator
{
}
-(CanvasView *)canvasViewWithFrame:(CGRect)aFrame;
@end
//ClothCanvasViewGenerator.m
#import "ClothCanvasView.h"
@implementation ClothCanvasViewGenerator
-(CanvasView *)canvasViewWithFrame:(CGRect)aFrame{
return [[ClothCanvasView alloc] initWithFrame:aFrame];
}
@end
4.3 CanvasViewController
//CanvasViewController.h
#import "CanvasView.h"
#import "CanvasViewGenerator.h"
@interface CanvasViewController : UIViewController
{
@private
CanvasView *_canvasView; //畫布視圖
}
@property (nonatomic, strong) CanvasView *canvasView;
- (void)loadCanvasViewWithGenerator:(CanvasViewGenerator *)generator;
@end
//CanvasViewController.m
// 實(shí)現(xiàn)viewDidLoad绢陌,進(jìn)行視圖加載后的追加設(shè)置。
// 通常視圖是從nib加載噩茄。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// 使用CanvasViewGenerator的工程方法取得默認(rèn)畫布視圖
CanvasViewGenerator *defaultGenerator = [[CanvasViewGenerator alloc] init];
[self loadCanvasViewWithGenerator:defaultGenerator];
}
// 限于篇幅下面,略去了無關(guān)的方法
#pragma mark Loading a CanvasView from a CanvasViewGenerator
-(void)loadCanvasViewWithGenerator:(CanvasViewGenerator *)generator
{
[_canvasView removeFromSuperview];
CGRect aFrame = CGRectMake(0, 0, 320, 436);
CanvasView *aCanvasView = [generator canvasViewWithFrame:aFrame];
[self setCanvasView:aCanvasView];
[self.view addSubview:_canvasView];
}
應(yīng)用程序通過把具體生成器的實(shí)例傳給-(void)loadCanvasViewWithGenerator:(CanvasViewGenerator *)generator
方法,來生成具體的畫布绩聘。
4.5 在Cocoa Touch框架中應(yīng)用工廠方法
例:NSNumber numberWith*方法
[NSNumber numberWithBool:bool];
[NSNumber numberWithChar:char];
4.6 總結(jié)
工廠方法從代碼中消除了對(duì)應(yīng)用程序特有類的耦合沥割。