何为原型模式?
原型模式:例如客户端知道抽象Prototype类,在运行时,抽象Prototype子类的任何对象都可以按客户端的意愿被复制。因此,无需手工创建就可以制造同一类型的多个实例。可以简单理解为创建第一个模版对象,然后通过复制(深拷贝)模版来创建新的对象。
从功能的角度看,不管什么对象,只要复制自身比手工实例化要好,都可以是原型对象。
何时使用原型模式?
1.需要创建的对象应独立于其类型与创建方式。是说想要创建的对象不能直接通过初始化函数来创建,创建方式不具有普遍性,比较复杂。
2.要实例化的类是在运行时决定的。是说在编写代码时,并不知道哪种对象会被创建,取决于用户的操作,且内部结构复杂。
3.不想要与产品层次相对应的工厂层次。是说不通过工厂方法或抽象工厂来控制产品的创建过程。
4.不用类的实例间的差异仅是状态的若干组合。因此复制相应数量的原型比手工实例化更加方便。
5.类不容易创建,比如每个组件可把其他组件作为子节点的组合对象。复制已有的组合对象并对副本进行修改会更加容易。
两种特别常见的情形:
1.有很多相关的类,其行为略有不同,,而且主要差异在于内部属性,如名称、图像。
2.需要使用组合(树型)对象作为其他东西的基础,例如,使用组合对象作为组建来构建另一个组件对象。
原理UML图
简单使用
定义协议
#import <Foundation/Foundation.h>
@protocol PrototypeProtocol <NSObject>
- (id)copy;
@end
Prototype子类
//.h
#import <Foundation/Foundation.h>
#import "PrototypeProtocol.h"
@interface Prototype : NSObject<PrototypeProtocol,NSCopying>
@property (nonatomic, copy) NSString * name;
@end
//.m
#import "Prototype.h"
@implementation Prototype
- (id)copyWithZone:(NSZone *)zone{
Prototype * prototype = [[self class] allocWithZone:zone];
prototype.name = self.name;
return prototype;
}
@end
Prototype子类遵守协议。
并一起遵守NSCopying协议,然后重写-(id)copyWithZone:(NSZone *)zone方法。
而且通过上述代码可以发现,我们并没有用copy方法,而是用copyWithZone:方法,这是因为NSObject协议没有声明copy方法,但是NSObject声明了NSObject型的接收器收到copy消息时,NSObject会依次向其采用了NSCopying协议的子类转发消息。子类要实现所需的NSCopying中定义的copyWithZone:方法,以返回自身的副本。如果子类没有实现此方法,会抛出NSInvalidArgumentException的实例。这就是为什么要让Prototype类采用NSCopying协议并为复制处理实现其copyWithZone:方法。而NSObject协议没有声明copy方法,所以在PrototypeProtocol协议声明它,以避免编译警告。
在重写时,使用了[self class]是因为希望其子类也能够复用这个复制方法。
//ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Prototype * p = [[Prototype alloc] init];
p.name = @"John";
Prototype * p1 = [p copy];
p1.name = @"Bob";
NSLog(@"p.name == %@----p1.name == %@",p.name,p1.name);
}
//p.name == John----p1.name == Bob
虽然使用的例子比较简单,但是便于理解,假如类的内部属性较多,实例化比较复杂,原型模式将会是非常简单的创建模式。