iOS設計模式(03):工廠方法

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圖形

相關文章
相關標籤/搜索