文档章节

iOS设计模式(03):工厂方法

H
 HillYoung
发布于 2015/02/04 18:06
字数 1807
阅读 21
收藏 1

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


本文转载自:http://www.cocoachina.com/ios/20130516/6219.html

H
粉丝 14
博文 100
码字总数 27117
作品 0
南京
程序员
私信 提问
移动开发之设计模式-工厂模式(IOS&Android)

资源 完全参照 工厂模式|菜鸟教程 ,但不包括IOS代码 工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳...

FlanneryZJ
2018/12/17
0
0
如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊
2018/05/26
0
0
移动开发之设计模式-抽象工厂模式(IOS&Android)

资源 完全参照 抽象工厂模式|菜鸟教程 ,但不包括IOS代码 抽象工厂模式 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型...

FlanneryZJ
2018/12/17
0
0
iOS设计模式(代码分析系列2:简单工厂模式)

简单工厂模式示例代码下载地址, 1、简述 首先需要说明一下,简单工厂模式不属于23种GOF设计模式之一。它也称作静态工作方法模式,是工厂方法模式的特殊实现(也就是说工厂模式包含简单工厂模...

召唤攻城狮
2014/09/09
5.4K
0
【干货】iOS开发学习中不易弄清楚的六种开发模式

在我们的实际开发中,架构模式多多少少也有几十种,在很多模式里,相信很多刚开始接触ios的程序员会遇到这类问题,本文小编就为大家详细解说这6种模式应用场景,帮助大家理清思路,学好ios开...

原来是泽镜啊
2018/04/30
20
0

没有更多内容

加载失败,请刷新页面

加载更多

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
57分钟前
5
0
Spring Boot 如何部署到 Linux 中的服务

打包完成后的 Spring Boot 程序如何部署到 Linux 上的服务? 你可以参考官方的有关部署 Spring Boot 为 Linux 服务的文档。 文档链接如下: https://docs.ossez.com/spring-boot-docs/docs/r...

honeymoose
59分钟前
5
0
Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

码农小胖哥
今天
6
0
ZetCode 教程翻译计划正式启动 | ApacheCN

原文:ZetCode 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 学习资源 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 ...

ApacheCN_飞龙
今天
4
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性:css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部