前言
在印刷术还没有普及的时代,人们常常用木头印章往纸上印一些常用的图形和文字,组合各种常用印章是往纸上大量复制同一信息的一种非常容易的方法。在许多面向对象的应用程序中,有些对象的创建代价过大或过于复杂。典型的例子是复制组合结构(比如,树型结构)。如果可以把某些对象变成印章,让其生成自身的复制品,就能节省创建它们所花费的大量精力。应用于 “复制 ”操作的模式称为原型模式。
什么是原型模式
原型(Prototype)模式是用于创建重复的对象,同时又能保证性能。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。在运行时,抽象 Prototype
子类的任何对象都可以被复制。利用已有的一个原型对象,快速地生成和原型对象一样的实例。尽管产品是用同一原型实例复制的,但是某些属性可以稍有不同。
何时使用原型模式
- 需要创建的对象应独立于其类型与创建方式。
- 要实例化的类是在运行时刻指定时。
- 为了避免创建一个与产品类层次平行的工厂类层次时
- 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并拷贝它们可能比每次用合适的状态手工实例化该类更方便一些。
- 类不容易创建,比如每个组件可把其它组件作为子节点的组合对象。复制已有的组合对象并对副本进行修改会更加容易。
原型模式的优缺点
优点
1、性能提高。
2、逃避构造函数的约束。
缺点
1、配备拷贝方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
2、必须遵守<NSCopying>
协议,实现 copy
接口。
原型模式的使用场景举例
- 资源优化场景。
- 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
- 性能和安全要求的场景
- 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
- 一个对象多个修改者的场景。
- 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
- 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过
copy
的方法创建一个对象,然后由工厂方法提供给调用者。
原型模式的实现
-
定义一个抽象类
Shape
,其遵守<NSCopying>
协议。@interface Shape : NSObject<NSCopying> @property (nonatomic, copy) NSString *Id; @property (nonatomic, copy) NSString *type; - (void)draw; @end
-
定义三个 Shape 的子类分别为
Rectangle
、Circle
和Square
@interface Rectangle : Shape @end @implementation Rectangle - (instancetype)init { self = [super init]; if (self) { self.type = @"Rectangle"; } return self; } - (void)draw{ NSLog(@"call Rectangle draw() method."); } @end @interface Circle : Shape @end @implementation Circle - (instancetype)init { self = [super init]; if (self) { self.type = @"Circle"; } return self; } - (void)draw{ NSLog(@"call Circle draw() method."); } @end @interface Square : Shape @end @implementation Square - (instancetype)init { self = [super init]; if (self) { self.type = @"Square"; } return self; } - (void)draw{ NSLog(@"call Square draw() method."); } @end
-
定义一个
ShapeCache
类,生成基于给定信息的实体类的对象。+(instancetype)loadCache{ ShapeCache *cache = [ShapeCache new]; Circle *circle = [Circle new]; circle.Id = @"1"; [cache saveShape:circle]; Square *square= [Square new]; square.Id = @"2"; [cache saveShape:square]; Rectangle *rectangle = [Rectangle new]; rectangle.Id = @"3"; [cache saveShape:rectangle]; return cache; } - (Shape *)getShape:(NSString *)shapeId{ Shape *cachedShape = [self objectForKey:shapeId]; return [cachedShape copy]; } - (void)saveShape:(Shape *)shape{ [self setObject:shape forKey:shape.Id]; }
当我们将保存的
Shape
应用的时候得到的是其副本,保存的Shape
作为绘制图形的模板。
总结
原型模式是用于对象创建的非常简单的模式,在 Objective-C 中,只需要遵守 <NSCopying>
协议,实现 copyWithZone:
实例方法,就可以通过 copy
方法得到副本。