原型模式:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式本质就是克隆对象,所以在对象初始化操作比较复杂的情况下,很实用,能大大降低耗时,提高性能,因为“不用重新初始化对象,而是动态地获得对象运行时的状态”。
相比工厂模式,原型模式减少了子类的构建。
实例:
当我们出版了一本书《Python 设计模式 1.0版》,若10 年后我们觉得这本书跟不上时代了,这时候需要去重写一本《Python 设计模式 2.0版》,那么我们是完全重写一本书呢?还是在原有《Python 设计模式 1.0版》的基础上进行修改呢?当然是后者,这样会省去很多排版、添加原有知识等已经做过的工作。
又比如:想用Photoshop画一只小狗。首先创建一个比较复杂图层对象(包括背景色,画笔粗细、颜色等等),然后用该图层对象画小狗。之后我又想画一只属性相同的大狗,难道我还要在重新创建一个图层对象吗?当然不同,直接复制之前创建的就可以了。
代码实现:
from copy import copy, deepcopy
class simpleLayer:
"""
设计一个图层对象,用background表示背景的RGBA,简单用content表示内容,除了直接绘画,还可以设置透明度。
"""
background=[0,0,0,0]
content="blank"
def getContent(self):
return self.content
def getBackground(self):
return self.background
def paint(self,painting):
self.content=painting
def setParent(self,p):
self.background[3]=p
def fillBackground(self,back):
self.background=back
def clone(self):
return copy(self)
def deep_clone(self):
return deepcopy(self)
if __name__=="__main__":
dog_layer=simpleLayer()
dog_layer.paint("Dog")
dog_layer.fillBackground([0,0,255,0])
print("Background:",dog_layer.getBackground())
print("Painting:",dog_layer.getContent())
another_dog_layer=dog_layer.clone()
# 通过复制(clone)这个动作实现画一只同样的狗
print("Background:", another_dog_layer.getBackground())
print("Painting:", another_dog_layer.getContent())
深浅拷贝:
浅拷贝会拷贝对象内容及其内容的引用或者子对象的引用,但不会拷贝引用的内容和子对象本身;而深拷贝不仅拷贝了对象和内容的引用,也会拷贝引用的内容。所以,一般深拷贝比浅拷贝复制得更加完全,但也更占资源(包括时间和空间资源)。
浅拷贝:
#浅拷贝
if __name__=="__main__":
dog_layer=simpleLayer()
dog_layer.paint("Dog")
dog_layer.fillBackground([0,0,255,0])
print("Original Background:",dog_layer.getBackground())
print("Original Painting:",dog_layer.getContent())
another_dog_layer=dog_layer.clone()
# another_dog_layer=dog_layer.deep_clone()
another_dog_layer.setParent(128)
another_dog_layer.paint("Puppy")
print("Original Background:", dog_layer.getBackground())
print("Original Painting:", dog_layer.getContent())
print("Copy Background:", another_dog_layer.getBackground())
print("Copy Painting:", another_dog_layer.getContent())
运行结果:
Original Background: [0, 0, 255, 0]
Original Painting: Dog
Original Background: [0, 0, 255, 128]
Original Painting: Dog
Copy Background: [0, 0, 255, 128]
Copy Painting: Puppy
可以看出在浅拷贝时setParent()方法在类another_dog_layer中并没有二次执行,而是直接从内存中dog_layer中拷贝过来(用的类dog_layer的)
深拷贝:
#深拷贝
if __name__=="__main__":
dog_layer=simpleLayer()
dog_layer.paint("Dog")
dog_layer.fillBackground([0,0,255,0])
print("Original Background:",dog_layer.getBackground())
print("Original Painting:",dog_layer.getContent())
#another_dog_layer=dog_layer.clone()
another_dog_layer=dog_layer.deep_clone()
another_dog_layer.setParent(128)
another_dog_layer.paint("Puppy")
print("Original Background:", dog_layer.getBackground())
print("Original Painting:", dog_layer.getContent())
print("Copy Background:", another_dog_layer.getBackground())
print("Copy Painting:", another_dog_layer.getContent())
执行结果:
Original Background: [0, 0, 255, 0]
Original Painting: Dog
Original Background: [0, 0, 255, 0]
Original Painting: Dog
Copy Background: [0, 0, 255, 128]
Copy Painting: Puppy
可以看出,再深拷贝时another_dog_layer的所有方法都是自己构建的。