iOS设计模式(03):工厂方法
2014-01-21 15:08
211 查看
原文;http://beyondvincent.com/blog/2013/05/16/23/
什么是工厂方法?
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)。
如下图所示,是工厂方法的类结构图:
![](http://beyondvincent.com/wp-content/uploads/2013/05/QQ20130516-4.png)
什么时候使用工厂方法?
当是如下情况是,可以使用工厂方法:
一个类不知道它所必须创建的对象的类时
一个类希望有它的子类决定所创建的对象时
更多关于工厂方法的介绍,可以参考本文最后给出的参考内容。下面我们就来看看在iOS中工厂方法的一种实现方法。
iOS中工厂方法的实现
如下有一个类图,该图描述了下面即将实现的工厂方法(利用工厂方法,创建出不同的形状)。其中BVShapeFactory为工厂方法的基类,BVShape为形状的基类,BVClient通过BVShapeFactory,利用 BVShapeFactory的子类(BVCircleShapeFactory和BVSquareShapeFactory)分别创建出BVCircleShape和BVSquareShape。![](http://beyondvincent.com/wp-content/uploads/2013/05/QQ20130516-5.png)
具体实现步骤如下(建议下载本文最后给出的代码实例,用Xcode查阅代码):
创建一个形状基类BVShape
该类中定义了形状的基本行为和属性,如下代码所示:
BVShape.h
// // BVShape.h // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #define BV_Exception_Format @"在%@的子类中必须override:%@方法" @interface BVShape : NSObject @property (nonatomic, weak)NSString *name; // 子类必须重写这个draw方法,否则会抛出异常错误 -(void)draw; @end
BVShape.m
// // BVShape.m // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVShape.h" @implementation BVShape -(id)init { self = [super init]; if (self) { // 做一些初始化任务 } return self; } -(void)draw { // 如果是通过BVShape的实例调用此处的draw,则绘制一个BVShape图形 if ([self isMemberOfClass:[BVShape class]]) { NSLog(@"绘制一个BVShape图形"); } else { // 如果是通过BVShape子类的实例调用了此处的draw,则抛出一个异常:表明子类并没有重写draw方法。 // 注:在OC中并没有abstract class的概念,只有protocol,如果在基类中只定义接口(没有具体方法的实现), // 则可以使用protocol,这样会更方便。 [NSException raise:NSInternalInconsistencyException format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)]; } } @end
在上面的代码中定义了一个draw方法,为了让子类必须实现该方法,在BVShape中做了特殊处理,具体内容可以看上面的代码,已经有注视了。
子类化形状基类
首先子类化一个圆形类:BVCircleShape。
BVCircleShape.h
// // BVCircleShape.h // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVShape.h" @interface BVCircleShape : BVShape @end
BVCircleShape.m
// // BVCircleShape.m // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVCircleShape.h" @implementation BVCircleShape -(void)draw { NSLog(@"绘制一个BVCircleShape图形"); } @end
在上面的子类中,重写了基类的draw方法。同样,我们再子类化一个正方形类,并重写draw方法,如下代码所示:
BVSquareShape.h
// // BVSquareShape.h // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVShape.h" @interface BVSquareShape : BVShape @end
BVSquareShape.m
// // BVSquareShape.m // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVSquareShape.h" @implementation BVSquareShape -(void)draw { NSLog(@"绘制一个BVSquareShape图形"); } @end
创建一个工厂方法的基类BVShapeFactory
BVShapeFactory.h
// // BVShapeFactory.h // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVShape.h" @interface BVShapeFactory : NSObject -(BVShape *) factoryMethod; @end
BVShapeFactory.m
// // BVShapeFactory.m // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVShapeFactory.h" @implementation BVShapeFactory -(BVShape *)factoryMethod { // 在此处,子类必须重写factoryMethod方法。当然,在工厂模式中,也可以在此处返回一个默认的Product。 // 如果是通过BVShapeFactory子类的实例调用了此处的factoryMethod,则抛出一个异常:表明子类并没有重写factoryMethod方法。 [NSException raise:NSInternalInconsistencyException format:BV_Exception_Format, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)]; // 下面这个return语句只是为了消除警告,实际上永远都不会执行到这里。 return nil; } @end
在上面的代码中,定义了一个factoryMethod,该类的子类必须实现该方法,通过实现该方法,返回一个具体的形状对象。下面来看看该类的子类化。
子类化工厂方法的基类
首先子类化一个圆形工厂方法BVCircleShapeFactory:
BVCircleShapeFactory.h
// // BVCircleShapeFactory.h // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVShapeFactory.h" #import "BVCircleShape.h" @interface BVCircleShapeFactory : BVShapeFactory @end
BVCircleShapeFactory.m
// // BVCircleShapeFactory.m // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVCircleShapeFactory.h" @implementation BVCircleShapeFactory -(BVShape *)factoryMethod { return [[BVCircleShape alloc] init]; } @end
如上代码所示,重写了factoryMethod,返回一个BVCircleShape实例。下面来看看另外一个子类BVSquareShapeFactory:
BVSquareShapeFactory.h
// // BVSquareShapeFactory.h // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVShapeFactory.h" #import "BVSquareShape.h" @interface BVSquareShapeFactory : BVShapeFactory @end
BVSquareShapeFactory.m
// // BVSquareShapeFactory.m // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVSquareShapeFactory.h" @implementation BVSquareShapeFactory -(BVShape *)factoryMethod { return [[BVSquareShape alloc] init]; } @end
该子类返回的是一个BVSquareShape实例。
工厂方法的使用
定义一个BVClient类,在该类中演示工厂方法的使用。代码如下:
BVClient.h
// // BVClient.h // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // @interface BVClient : NSObject -(void)doSomething; @end
BVClient.m
// // BVClient.m // FactoryMethodPattern // // Created by BeyondVincent on 13-5-15. // Copyright (c) 2013年 BeyondVincent. All rights reserved. // #import "BVClient.h" #import "BVShapeFactory.h" #import "BVCircleShapeFactory.h" #import "BVSquareShapeFactory.h" #import "BVShape.h" #import "BVCircleShape.h" #import "BVSquareShape.h" @implementation BVClient -(void)doSomething { // 工厂方法的实例化 BVShapeFactory *circleShapefactory = [[BVCircleShapeFactory alloc] init]; BVShapeFactory *squareShapefactory = [[BVSquareShapeFactory alloc] init]; // 通过工厂方法实例化对应的形状 BVShape *circleShape = [circleShapefactory factoryMethod]; BVShape *squareShape = [squareShapefactory factoryMethod]; // 调用形状的方法 [circleShape draw]; [squareShape draw]; } @end
如上代码所示,首先实例化两个工厂方法,并通过工厂方法创建出对应的形状,最后调用形状的draw方法进行测试。会在控制台窗口输出如下内容:
2013-05-16 10:12:46.292 FactoryMethodPattern[2845:c07] 绘制一个BVCircleShape图形 2013-05-16 10:12:46.295 FactoryMethodPattern[2845:c07] 绘制一个BVSquareShape图形
代码实例
本文涉及到的相关实例代码和PDF归档可以到点击下图下载:![](http://beyondvincent.com/wp-content/uploads/2013/05/5555.png)
![](http://beyondvincent.com/wp-content/uploads/2013/05/pdf-icon.png)
参考
在学习工厂方法时,参考了如下一些文章和视频:工厂方法wiki上对工厂方法的介绍
Class
Factory Methods 苹果官网对类工厂方法的介绍
iOS
Patterns. Factory Method(一篇介绍工厂方法的文章,俄文,需要楼梯)
What
Is the Factory Method Pattern?(Pro Objective-C Design Patterns for iOS书中对工厂方法的介绍)
.NET设计模式(5):工厂方法模式(Factory
Method)
java实现工厂方法
JAVA:
Factory Method Design Patternyoutube上一个关于工厂方法的视频介绍
iphone-sdk-difference-between-iskindofclass-and-ismemberofclass iskindofclass和ismemberofclass区别
_____________
本文由破船原创
转载请注明出处:BeyondVincent的博客
相关文章推荐
- iOS设计模式(03):工厂方法
- iOS设计模式(03):工厂方法
- iOS设计模式(03):工厂方法
- iOS 设计模式之简单工厂方法模式(SimpleFactoryMethod)
- iOS设计模式-工厂方法
- iOS设计模式:工厂方法
- iOS设计模式-工厂方法
- iOS设计模式-工厂方法
- iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
- iOS设计模式:工厂方法
- iOS设计模式:工厂方法
- Object-C编程之道 iOS设计模式解析--工厂方法
- iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
- iOS经常使用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
- 设计模式系列-03-创建模式-工厂方法
- GoF 23个经典的设计模式03--创建模式之工厂方法(未完代续)
- iOS学习笔记(5)——设计模式之工厂方法、抽象工厂
- iOS设计模式:工厂方法
- ios设计模式读书笔记----Factory Method(工厂方法)