iOS设计模式(03):工厂方法
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
GOF是這樣描述工廠模式的:
“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”
?
在基類中定義創(chuàng)建對象的一個(gè)接口,讓子類決定實(shí)例化哪個(gè)類。工廠方法讓一個(gè)類的實(shí)例化延遲到子類中進(jìn)行。
?
工廠方法要解決的問題是對象的創(chuàng)建時(shí)機(jī),它提供了一種擴(kuò)展的策略,很好地符合了開放封閉原則。工廠方法也叫做虛構(gòu)造器(Virtual Constructor)。
?
如下圖所示,是工廠方法的類結(jié)構(gòu)圖:
?
什么時(shí)候使用工廠方法?
當(dāng)是如下情況是,可以使用工廠方法:一個(gè)類不知道它所必須創(chuàng)建的對象的類時(shí),一個(gè)類希望有它的子類決定所創(chuàng)建的對象時(shí)。
?
更多關(guān)于工廠方法的介紹,可以參考本文最后給出的參考內(nèi)容。下面我們就來看看在iOS中工廠方法的一種實(shí)現(xiàn)方法。
?
iOS中工廠方法的實(shí)現(xiàn)
如下有一個(gè)類圖,該圖描述了下面即將實(shí)現(xiàn)的工廠方法(利用工廠方法,創(chuàng)建出不同的形狀)。其中BVShapeFactory為工廠方法的基類,BVShape為形狀的基類,BVClient通過BVShapeFactory,利用 BVShapeFactory的子類(BVCircleShapeFactory和BVSquareShapeFactory)分別創(chuàng)建出BVCircleShape和BVSquareShape。
?
如下圖,是在Xcode中創(chuàng)建的相關(guān)文件
?
?
(具體實(shí)現(xiàn)步驟如下(建議下載本文最后給出的代碼實(shí)例,用Xcode查閱代碼):
?
1.創(chuàng)建一個(gè)形狀基類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.// 子類必須重寫這個(gè)draw方法,否則會(huì)拋出異常錯(cuò)誤
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. ? ? ? ?// 做一些初始化任務(wù)
18. ? ?}
19. ? ?return self;
20.}
21.?
22.-(void)draw
23.{
24. ? ?// 如果是通過BVShape的實(shí)例調(diào)用此處的draw,則繪制一個(gè)BVShape圖形
25. ? ?if ([self isMemberOfClass:[BVShape class]]) {
?26. ? ? ? NSLog(@"繪制一個(gè)BVShape圖形");
27. ? ?} else {
28. ? ? ? ?// 如果是通過BVShape子類的實(shí)例調(diào)用了此處的draw,則拋出一個(gè)異常:表明子類并沒有重寫draw方法。
29. ? ? ? ?// 注:在OC中并沒有abstract class的概念,只有protocol,如果在基類中只定義接口(沒有具體方法的實(shí)現(xiàn)),
30. ? ? ? ?// ? ?則可以使用protocol,這樣會(huì)更方便。?
31. ? ? ? ?[NSException raise:NSInternalInconsistencyException
32. ? ? ? ? ? ? ? ? ? ?format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)];
33. ? ?}
34.}
35.?
36.@end
?
?
在上面的代碼中定義了一個(gè)draw方法,為了讓子類必須實(shí)現(xiàn)該方法,在BVShape中做了特殊處理,具體內(nèi)容可以看上面的代碼,已經(jīng)有注視了。
?
2.子類化形狀基類。首先子類化一個(gè)圓形類: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(@"繪制一個(gè)BVCircleShape圖形");
16.}
17.?
18.@end
?
?
在上面的子類中,重寫了基類的draw方法。同樣,我們再子類化一個(gè)正方形類,并重寫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(@"繪制一個(gè)BVSquareShape圖形");
16.}
17.?
18.@end
?
3.創(chuàng)建一個(gè)工廠方法的基類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方法。當(dāng)然,在工廠模式中,也可以在此處返回一個(gè)默認(rèn)的Product。
16. ? ?// 如果是通過BVShapeFactory子類的實(shí)例調(diào)用了此處的factoryMethod,則拋出一個(gè)異常:表明子類并沒有重寫factoryMethod方法。
17. ? ?[NSException raise:NSInternalInconsistencyException
18. ? ? ? ? ? ? ? ?format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)];
19.?
20. ? ?// 下面這個(gè)return語句只是為了消除警告,實(shí)際上永遠(yuǎn)都不會(huì)執(zhí)行到這里。
21. ? ?return nil;
22.}
23.?
24.@end
?
在上面的代碼中,定義了一個(gè)factoryMethod,該類的子類必須實(shí)現(xiàn)該方法,通過實(shí)現(xiàn)該方法,返回一個(gè)具體的形狀對象。下面來看看該類的子類化。
?
4.子類化工廠方法的基類。首先子類化一個(gè)圓形工廠方法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,返回一個(gè)BVCircleShape實(shí)例。下面來看看另外一個(gè)子類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
?
該子類返回的是一個(gè)BVSquareShape實(shí)例。
?
5.工廠方法的使用。定義一個(gè)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. ? ?// 工廠方法的實(shí)例化
24. ? ?BVShapeFactory *circleShapefactory = [[BVCircleShapeFactory alloc] init];
25. ? ?BVShapeFactory *squareShapefactory = [[BVSquareShapeFactory alloc] init];
26.?
27. ? ?// 通過工廠方法實(shí)例化對應(yīng)的形狀
28. ? ?BVShape *circleShape = [circleShapefactory factoryMethod];
29. ? ?BVShape *squareShape = [squareShapefactory factoryMethod];
30.?
31. ? ?// 調(diào)用形狀的方法
32. ? ?[circleShape draw];
33. ? ?[squareShape draw];
34.}
35.?
36.@end
?
如上代碼所示,首先實(shí)例化兩個(gè)工廠方法,并通過工廠方法創(chuàng)建出對應(yīng)的形狀,最后調(diào)用形狀的draw方法進(jìn)行測試。會(huì)在控制臺(tái)窗口輸出如下內(nèi)容:
2013-05-16 10:12:46.292 FactoryMethodPattern[2845:c07] 繪制一個(gè)BVCircleShape圖形
2013-05-16 10:12:46.295 FactoryMethodPattern[2845:c07] 繪制一個(gè)BVSquareShape圖形
轉(zhuǎn)載于:https://my.oschina.net/u/1432769/blog/375410
總結(jié)
以上是生活随笔為你收集整理的iOS设计模式(03):工厂方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android-RelativeLayo
- 下一篇: asp.net ajax控件工具集 Au