2019独角兽企业重金招聘Python工程师标准>>>

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

转载于:https://my.oschina.net/u/1432769/blog/375410

iOS设计模式(03):工厂方法相关推荐

  1. python类是实例的工厂_Python设计模式之工厂方法模式实例详解

    本文实例讲述了Python设计模式之工厂方法模式.分享给大家供大家参考,具体如下: 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类, ...

  2. 设计模式复习-工厂方法模式

     设计模式复习-工厂方法模式 相对于简单工厂,工厂方法是把算法类的实例化延迟到了调用者那去做,调用者根据自己的需要,自己实例化相关的工厂并且生产相关算法.这么做是因为简单工厂是不满足OCP的,因为如果 ...

  3. C#设计模式(3)——工厂方法模式

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是--简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

  4. 设计模式之工厂方法模式(创建型)

    一.模式定义 工厂方法模式:又称工厂模式,也叫虚拟构造器模式,属于构建型设计模式,工厂方法模式是在简单工厂模式上进行拓展,生产产品的过程由具体工厂类实现,基类只实现接口,这使得工厂方法模式可以在不修改 ...

  5. 设计模式之工厂方法模式应用例题

    设计模式之工厂方法模式应用例题 题目描述 类结构图及相关说明 程序代码 运行结果 题目描述 现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReade ...

  6. 设计模式:工厂方法模式(Factory method)

    设计模式:工厂方法模式(Factory method) 一.问题 在前一章中通过披萨的实例介绍了简单工厂模式.在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨. ...

  7. 【设计模式】工厂方法模式(C#)

    [设计模式]工厂方法模式 1.概述 针对简单工厂中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则. 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象.工厂方法使一个产品类的实例化 ...

  8. 二、java设计模式之工厂方法+抽象工厂模式(创建型设计模式)

    创建型设计模式-工厂模式和应用 工厂模式介绍: 它提供了一种创建对象的最佳方式,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象 例子: 需要购买一辆车,不用管 ...

  9. 一文叫你弄懂Java设计模式之工厂方法模式:图解+日志记录器代码实例

    文章目录 详解Java设计模式之工厂方法模式 案例引入工厂方法模式 工厂方法模式 定义 案例分析 UML类图分析 代码分析 工厂方法的重载 工厂方法的隐藏 模式优点 模式缺点 模式适用环境 详解Jav ...

最新文章

  1. mysql的or能去重吗_mysql条件查询中AND与OR联合使用的注意事项!
  2. python绘制一个圆_Python在网格上绘制一个填充的“圆”
  3. javascript技术教程蔡敏_程序员都必掌握的前端教程之JavaScript基础教程(上)
  4. !Important:CSS中!important的作用用于Ie6.0 与Ie7.0、firefox
  5. python 的笔记
  6. 《python cookbook》chapter 1
  7. Theano 中文文档 0.9 - 7.2.4 条件
  8. Python中list,tuple,dict,set的区别和用法
  9. 中等职业技术学校计算机课件,中等职业技术学校计算机教学论文
  10. 湖北校园天翼飞young使用路由器上网
  11. Vue经典开源项目汇总
  12. matlab信号处理——数据处理基础
  13. git FETCH_HEAD 版本回滚 ORIG_HEAD
  14. javascript Date format(js日期格式化)
  15. 区块链研究实验室-首次提出如何确保区块链分片技术的数据完整性
  16. 软件体系结构的基本概念与作用
  17. 最小编辑距离 (MED)实现-Python
  18. java poi jar包下载_poi.jar下载-poi.jar包下载 (3.8/3.9/3.10)版--pc6下载站
  19. js 中文转拼音缩写
  20. Protobuf是什么?

热门文章

  1. mysql完整字段包括_MySQL字段类型最全解析
  2. windows编程一日一练(2)
  3. 怎么用计算机算亩数,怎样用手机测量亩数?
  4. python 九宫重排_[蓝桥杯][历届试题]九宫重排 (Python代码)(bfs+集合)
  5. 帆软日期控件变灰_FineReport-JS脚本常见日期使用整理
  6. weiler-atherton多边形裁剪算法_EAST算法超详细源码解析:数据预处理与标签生成...
  7. 一次ajax多次回调结果,Ajax异步的回调函数执行了多遍
  8. queue源码java_看看AbstractQueue源码Java9
  9. bat判断文本中是否存在一个相同内容比较_Excel中的9个逻辑函数都不掌握,还敢称Excel达人?...
  10. rust(10)-函数指针