原型模式
生活中的例子: 印刷术【刻画】、简历、模具
QR:创建一个对象过程过大、过于复杂? eg: 树结构
AN :重建对象并做轻微改动。eg:复制组合结构。
拷贝(浅拷贝、深拷贝) —— 原型模式
定义:
用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象
扩展描述:其实就是从一个对象再创建另一个可定制的对象,而不需要任何创建的细节。
好处:一般在初始化的信息不发生变化的情况下,克隆是最好的方法。 这既隐藏了对象呢创建的细节,又对性能是大大的提高。

问题: 如果里面的属性是值类型的,clone直接就拷贝出来了,如果是对象类型,则会复制引用,而不复制对象。 —— 原始对象和复制的对象引用是同一个对象。 —————— 【深拷贝和浅拷贝的问题】
//OC 实现一个简单的例子验证一下
// student 没有实现对应的copy, person实现对应的copy
@interface XNStudent : NSObject
@property (nonatomic, copy) NSString *name;
@end
@interface XNPerson : NSObject<NSCopying>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, strong) XNStudent *student;
@end
- (id)copyWithZone:(NSZone *)zone {
XNPerson *cpy = [XNPerson allocWithZone:zone];
if (cpy) {
cpy.name = self.name;
cpy.age = self.age;
cpy.student = self.student;
// cpy.student = [self.student copy]; 如果这样修改,将会出现错误。 应该在student里面实现这个copying协议
}
return cpy;
}

深拷贝: 注意拷贝对象和资源本身,而不只是指针。
进行修改
//<NSCopying> 实现这个协议,
// 实现下面的方法
- (id)copyWithZone:(NSZone *)zone {
XNStudent *cpy = [[self class] allocWithZone:zone];
if (cpy) {
cpy.name = self.name;
}
return cpy;
}

PS: 上面可以卡卡拿到
在OC里面,如果没有实现NSCopying协议里面的copywithzone: 方法,copy出来的对象是浅拷贝,如果实现了,就是深拷贝。
QR:什么时候使用原型模式?
AN:
1)需要创建的对象应独立于其他类型与创建方式 【特殊性】
2)要实例化的类是在运行时决定的。
3)不想要与产品层次相对应的工厂层次。 【???】
4)不同类的实例间的差异仅仅是状态的若干组合。 因此赋值响应数量的原型比手工实例化更加方便。对象间差异较小
5)类不容易创建, eg: 每个组件可把其他组件作为子节点的组合对象。 复制已有的组合对象并对副本进行修改更加容易。
PS:
1、对象间差异小
2、参数较多【操作不易】
3、对象结构复杂【不容易创建】
4、需要的对象的特殊性【独立性】
5、性能上的优化【eg:CPU操作少,内存已经知道大小,不用再去算了】
常常使用次模式的场景
- 有很多相关的类,其行为略有不同。
- 需要使用组合(树型)对象作为其他东西的基础。 eg: 使用组合对象作为组件来构建另一个组合对象。
《iOS设计模式中的绘图例子》
vertex , dot, stroke 这人几个都是遵循同样的一个接口。 里面有关的属性,我们可以声明对应的动态以及实现的关系。 来处理这个有没有实现对应的属性。【这个是一个很好的实现方式】
// vertex拷贝
- (id)copyWithZone:(NSZone *)zone;
{
return [[[self class] allocWithZone:zone] initWithLocation:self.location];
}
// dot拷贝
- (id)copyWithZone:(NSZone *)zone {
Dot *copy = [[[self class] allocWithZone:zone] initWithLocation:self.location];
// 复制颜色, 相当于重新创建一个颜色对象
[copy setColor:[UIColor colorWithCGColor:[self.color CGColor]]];
copy.size = self.size;
return copy;
}
// stroke的拷贝
- (id)copyWithZone:(NSZone *)zone {
Stroke *copy = [[[self class] allocWithZone:zone] init];
copy.color = [UIColor colorWithCGColor:self.color.CGColor];
copy.size = self.size;
for (id<Mark> child in self.children) {
id<Mark> childCopy = [child copy];
[copy addMark:childCopy];
}
return copy;
}
这里的使用场景是:我们需要保存一份当时的状态【快照】。 所以,需要拷贝一份数据进行保存。
参考博客
参考0x00