GOF是這樣描述工廠模式的:ide
「Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.」測試
在基類中定義建立對象的一個接口,讓子類決定實例化哪一個類。工廠方法讓一個類的實例化延遲到子類中進行。atom
工廠方法要解決的問題是對象的建立時機,它提供了一種擴展的策略,很好地符合了開放封閉原則。工廠方法也叫作虛構造器(Virtual Constructor)。spa
以下圖所示,是工廠方法的類結構圖:.net
何時使用工廠方法?code
當是以下狀況是,可使用工廠方法:一個類不知道它所必須建立的對象的類時,一個類但願有它的子類決定所建立的對象時。orm
更多關於工廠方法的介紹,能夠參考本文最後給出的參考內容。下面咱們就來看看在iOS中工廠方法的一種實現方法。對象
iOS中工廠方法的實現接口
以下有一個類圖,該圖描述了下面即將實現的工廠方法(利用工廠方法,建立出不一樣的形狀)。其中BVShapeFactory爲工廠方法的基類,BVShape爲形狀的基類,BVClient經過BVShapeFactory,利用 BVShapeFactory的子類(BVCircleShapeFactory和BVSquareShapeFactory)分別建立出BVCircleShape和BVSquareShape。ci
以下圖,是在Xcode中建立的相關文件
(具體實現步驟以下(建議下載本文最後給出的代碼實例,用Xcode查閱代碼):
1.建立一個形狀基類BVShape。該類中定義了形狀的基本行爲和屬性,以下代碼所示:
BVShape.h
1.//
2.// BVShape.h
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#define BV_Exception_Format @"在%@的子類中必須override:%@方法"
10.
11.@interface BVShape : NSObject
12.
13.@property (nonatomic, weak)NSString *name;
14.
15.// 子類必須重寫這個draw方法,不然會拋出異常錯誤
16.-(void)draw;
17.
18.@end
BVShape.m
1.//
2.// BVShape.m
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVShape.h"
10.
11.@implementation BVShape
12.
13.-(id)init
14.{
15. self = [super init];
16. if (self) {
17. // 作一些初始化任務
18. }
19. return self;
20.}
21.
22.-(void)draw
23.{
24. // 若是是經過BVShape的實例調用此處的draw,則繪製一個BVShape圖形
25. if ([self isMemberOfClass:[BVShape class]]) {
26. NSLog(@"繪製一個BVShape圖形");
27. } else {
28. // 若是是經過BVShape子類的實例調用了此處的draw,則拋出一個異常:代表子類並無重寫draw方法。
29. // 注:在OC中並無abstract class的概念,只有protocol,若是在基類中只定義接口(沒有具體方法的實現),
30. // 則可使用protocol,這樣會更方便。
31. [NSException raise:NSInternalInconsistencyException
32. format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)];
33. }
34.}
35.
36.@end
在上面的代碼中定義了一個draw方法,爲了讓子類必須實現該方法,在BVShape中作了特殊處理,具體內容能夠看上面的代碼,已經有注視了。
2.子類化形狀基類。首先子類化一個圓形類:BVCircleShape。
BVCircleShape.h
1.//
2.// BVCircleShape.h
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVShape.h"
10.
11.@interface BVCircleShape : BVShape
12.
13.@end
BVCircleShape.m
1.//
2.// BVCircleShape.m
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVCircleShape.h"
10.
11.@implementation BVCircleShape
12.
13.-(void)draw
14.{
15. NSLog(@"繪製一個BVCircleShape圖形");
16.}
17.
18.@end
在上面的子類中,重寫了基類的draw方法。一樣,咱們再子類化一個正方形類,並重寫draw方法,以下代碼所示:
BVSquareShape.h
1.//
2.// BVSquareShape.h
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVShape.h"
10.
11.@interface BVSquareShape : BVShape
12.
13.@end
BVSquareShape.m
1.//
2.// BVSquareShape.m
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVSquareShape.h"
10.
11.@implementation BVSquareShape
12.
13.-(void)draw
14.{
15. NSLog(@"繪製一個BVSquareShape圖形");
16.}
17.
18.@end
3.建立一個工廠方法的基類BVShapeFactory
BVShapeFactory.h
1.//
2.// BVShapeFactory.h
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVShape.h"
10.
11.@interface BVShapeFactory : NSObject
12.
13.-(BVShape *) factoryMethod;
14.
15.@end
BVShapeFactory.m
1.//
2.// BVShapeFactory.m
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVShapeFactory.h"
10.
11.@implementation BVShapeFactory
12.
13.-(BVShape *)factoryMethod
14.{
15. // 在此處,子類必須重寫factoryMethod方法。固然,在工廠模式中,也能夠在此處返回一個默認的Product。
16. // 若是是經過BVShapeFactory子類的實例調用了此處的factoryMethod,則拋出一個異常:代表子類並無重寫factoryMethod方法。
17. [NSException raise:NSInternalInconsistencyException
18. format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)];
19.
20. // 下面這個return語句只是爲了消除警告,實際上永遠都不會執行到這裏。
21. return nil;
22.}
23.
24.@end
在上面的代碼中,定義了一個factoryMethod,該類的子類必須實現該方法,經過實現該方法,返回一個具體的形狀對象。下面來看看該類的子類化。
4.子類化工廠方法的基類。首先子類化一個圓形工廠方法BVCircleShapeFactory:
BVCircleShapeFactory.h
1.//
2.// BVCircleShapeFactory.h
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVShapeFactory.h"
10.#import "BVCircleShape.h"
11.
12.@interface BVCircleShapeFactory : BVShapeFactory
13.
14.@end
BVCircleShapeFactory.m
1.//
2.// BVCircleShapeFactory.m
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVCircleShapeFactory.h"
10.
11.@implementation BVCircleShapeFactory
12.
13.-(BVShape *)factoryMethod
14.{
15. return [[BVCircleShape alloc] init];
16.}
17.
18.@end
如上代碼所示,重寫了factoryMethod,返回一個BVCircleShape實例。下面來看看另一個子類BVSquareShapeFactory:
BVSquareShapeFactory.h
1.//
2.// BVSquareShapeFactory.h
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVShapeFactory.h"
10.#import "BVSquareShape.h"
11.
12.@interface BVSquareShapeFactory : BVShapeFactory
13.
14.@end
BVSquareShapeFactory.m
1.//
2.// BVSquareShapeFactory.m
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVSquareShapeFactory.h"
10.
11.@implementation BVSquareShapeFactory
12.
13.-(BVShape *)factoryMethod
14.{
15. return [[BVSquareShape alloc] init];
16.}
17.
18.@end
該子類返回的是一個BVSquareShape實例。
5.工廠方法的使用。定義一個BVClient類,在該類中演示工廠方法的使用。代碼以下:
BVClient.h
1.//
2.// BVClient.h
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.@interface BVClient : NSObject
10.
11.-(void)doSomething;
12.
13.@end
BVClient.m
1.//
2.// BVClient.m
3.// FactoryMethodPattern
4.//
5.// Created by BeyondVincent on 13-5-15.
6.// Copyright (c) 2013年 BeyondVincent. All rights reserved.
7.//
8.
9.#import "BVClient.h"
10.
11.#import "BVShapeFactory.h"
12.#import "BVCircleShapeFactory.h"
13.#import "BVSquareShapeFactory.h"
14.
15.#import "BVShape.h"
16.#import "BVCircleShape.h"
17.#import "BVSquareShape.h"
18.
19.@implementation BVClient
20.
21.-(void)doSomething
22.{
23. // 工廠方法的實例化
24. BVShapeFactory *circleShapefactory = [[BVCircleShapeFactory alloc] init];
25. BVShapeFactory *squareShapefactory = [[BVSquareShapeFactory alloc] init];
26.
27. // 經過工廠方法實例化對應的形狀
28. BVShape *circleShape = [circleShapefactory factoryMethod];
29. BVShape *squareShape = [squareShapefactory factoryMethod];
30.
31. // 調用形狀的方法
32. [circleShape draw];
33. [squareShape draw];
34.}
35.
36.@end
如上代碼所示,首先實例化兩個工廠方法,並經過工廠方法建立出對應的形狀,最後調用形狀的draw方法進行測試。會在控制檯窗口輸出以下內容:
2013-05-16 10:12:46.292 FactoryMethodPattern[2845:c07] 繪製一個BVCircleShape圖形
2013-05-16 10:12:46.295 FactoryMethodPattern[2845:c07] 繪製一個BVSquareShape圖形