python 设计模式之原型模式 Prototype Pattern
#引入
例子1:
孙悟空拔下一嘬猴毛,轻轻一吹就会变出好多的孙悟空来。
例子2:寄个快递
下面是一个邮寄快递的场景:
“给我寄个快递。”顾客说。
“寄往什么地方?寄给……?”你问。
“和上次差不多一样,只是邮寄给另外一个地址,这里是邮寄地址……”顾客一边说一边把写有邮寄地址的纸条给你。
“好!”你愉快地答应,因为你保存了用户的以前邮寄信息,只要复制这些数据,然后通过简单的修改就可以快速地创建新的快递数据了。
# 原型模式概念
用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象
是建造者模式
#原型模式使用场景
1)资源优化场景。类初始化需要消耗非常多的资源,这个资源包括数据,硬件资源等,可通过原型复制避免这些消耗
2)通过new产生一个对象需要非常繁琐的数据准备或访问权限,这时可以使用原型模式
3)一个对象需要提供给其他对象访问,而且每个调用者可能都需要修改其值时?可以考虑使用原型模式复制多个对象供调用者使用,即保护性拷贝
4)性能和安全要求的场景。
#原型模式的优点
1)当创建的对象实例较为复杂的时候,使用原型模式可以简化对象的创建过程!
2)扩展性好,由于写原型模式的时候使用了抽象原型类,在客户端进行编程的时候可以将具体的原型类通过配置进行读取。
2)可以使用深度克隆来保存对象的状态,使用原型模式进行复制。当你需要恢复到某一时刻就直接跳到。比如我们的idea种就有历史版本,或则SVN中也有这样的操作。非常好用!
#原型模式的缺点
1)配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。
2)必须实现 Cloneable 接口。
#原型模式的角色
1)抽象原型(Prototype)角色:规定了具体原型对象必须实现的接口(如果要提供深拷贝,则必须具有实现clone的规定)
2)具体原型(ConcretePrototype):从抽象原型派生而来,是客户程序使用的对象,即被复制的对象,需要实现抽象原型角色所要求的接口。
3)客户(Client)角色:使用原型对象的客户程序
#原型模式的主意事项
对象拷贝的时候构造函数是不会执行的,原因在于拷贝是直接在堆中进行,这其实也可以理解,new的时候,JVM要走一趟类加载流程,这个流程非常麻烦,在类加载流程中会调用构造函数,最后生成的对象会放到堆中,而拷贝就是直接拷贝堆中的现成的二进制对象,然后重新一个分配内存块。
#浅克隆
仅仅复制所克隆的对象,而不复制它所引用的对象。
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
#深克隆
把要复制的对象所引用的对象都复制了一遍。
那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。
#举个例子
这个设计模式很好理解,而且已经嵌入到了语言中,拿andy的例子作参考
from copy import copy,deepcopy #原型抽象类 class Prototype: def clone(slef): pass def deep_clone(self): pass #workexperience类 class WorkExperience: def __init__(self): self.timearea='' self.company='' def set_workexperience(self,timearea,company): self.timearea=timearea self.company=company #Resume类 class Resume(Prototype): def __init__(self,name): self.name=name self.workexperience=WorkExperience() def set_personinfo(self,sex,age): self.sex=sex self.age=age pass def set_workexperience(self,timearea,company): self.workexperience.set_workexperience(timearea,company) def display(self): print(self.name) print(self.sex,self.age) print('work experience',self.workexperience.timearea,self.workexperience.company) def clone(self): return copy(self) def deep_clone(self): return deepcopy(self) if __name__=='__main__': obj1=Resume('uu') obj2=obj1.clone() obj3=obj1.deep_clone() obj1.set_personinfo('male',28) obj1.set_workexperience('2001-2003','developing') obj2.set_personinfo('male',26) obj2.set_workexperience('2004-2006','BA') obj3.set_personinfo('male',26) obj3.set_workexperience('2011-2012','testing') obj1.display() obj2.display() obj3.display()
#参考
https://zhidao.baidu.com/question/569131711.html
https://blog.csdn.net/weixin_30416497/article/details/96400396
https://blog.csdn.net/asffghfgfghfg1556/article/details/81702164
https://blog.csdn.net/qq_40709468/article/details/82316418
https://www.runoob.com/design-pattern/prototype-pattern.html
https://www.cnblogs.com/fengyumeng/p/10646487.html
https://blog.51cto.com/9291927/1970104
https://www.cnblogs.com/onepiece-andy/p/python_prototype_pattern.html