您的位置:首页 > 移动开发 > IOS开发

iOS设计模式:工厂方法

2013-08-21 14:51 525 查看
什么是工厂方法?

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.”

在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。

工厂方法要解决的问题是对象的创建时机,它提供了一种扩展的策略,很好地符合了开放封闭原则。工厂方法也叫做虚构造器(Virtual Constructor)。

如下图所示,是工厂方法的类结构图:



什么时候使用工厂方法?

当是如下情况是,可以使用工厂方法:一个类不知道它所必须创建的对象的类时,一个类希望有它的子类决定所创建的对象时。

更多关于工厂方法的介绍,可以参考本文最后给出的参考内容。下面我们就来看看在iOS中工厂方法的一种实现方法。

iOS中工厂方法的实现

如下有一个类图,该图描述了下面即将实现的工厂方法(利用工厂方法,创建出不同的形状)。其中BVShapeFactory为工厂方法的基类,BVShape为形状的基类,BVClient通过BVShapeFactory,利用 BVShapeFactory的子类(BVCircleShapeFactory和BVSquareShapeFactory)分别创建出BVCircleShape和BVSquareShape。



如下图,是在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图形

本文涉及到的相关实例代码:github下载地址

来源:破船的博客
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: