原型模式(Prototype Pattern)
定义
“Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)”
《设计模式之禅》
原型模式可以减小new创建对象,降低性能损耗。原型模式直接执行二进制的内存拷贝。并且原型模式可以用于多个访问者需要修改同一个对象的情况,可以将对象通过原型模式复制多分进行修改。
UML 示例
由于原型模式就是一个对象的副本,对于python来说,可以执行copy.copy() copy.deepcopy()函数,就实现了原型模式,很简单,为啥可说的,重要的是掌握原型模式的应用场景最重要。
代码实现
from collections import OrderedDict
import copy
class Book:
def __init__(self, name, authors, price, **rest):
self.name = name
self.authors = authors
self.price = price
self.__dict__.update(rest)
super().__init__()
def __str__(self):
'''
__str__ 函数是object定义的函数,用来执行print是打印字符串时的输出结果
'''
mylist = []
# OrderDict 有序字典,按照插入顺序将字典排序,很有用的库函数
ordered = OrderedDict(sorted(self.__dict__.items()))
for i in ordered.keys():
mylist.append('{}:{}'.format(i, ordered[i]))
if i == 'price':
mylist.append('$')
mylist.append('\n')
return ''.join(mylist)
class Prototype:
'''
实现一个通用的原型类,可以存储各种类的__dict__信息,不过需要一个identifier作为唯一标识
'''
def __init__(self):
self.objects = dict()
def register(self, identifier, obj):
self.objects[identifier] = obj
def unregister(self, identifier):
del self.objects[identifier]
def clone(self, identifier, **attr):
found = self.objects.get(identifier)
if not found:
raise ValueError('Incorrect object identifier:{}'.format(identifier))
obj = copy.deepcopy(found)
obj.__dict__.update(attr)
return obj
def main():
b1 = Book('The C Programming Language', ('Brian W.Kernighan', 'Dennis M.Ritchie'), price=118, publisher='Prentice Hall', length=228, publication_date='1978-02-22', tags=('C', 'programming', 'algorithms', 'data structures'))
prototype = Prototype()
cid = 'k&r-first' # 第一book对象的唯一标识,方便clone
prototype.register(cid, b1) # 注册一本书
# 通过clone方法复制b2这本书
b2 = prototype.clone(cid, name='The C Programming Language(ANSI)', price=48.99, length=274, publication_date='1988-04-01', edition=2)
for i in (b1, b2):
print(i)
print('ID b1: {} != ID b2: {}'.format(id(b1), id(b2)))
if __name__ == "__main__":
main()
知识点
关于原型模式没有太难的知识点,我们只要重点了解python中的copy.copy()和copy.deepcopy()即可。
copy.copy()浅副本,依赖引用;我们可以引入数据共享和写时复制一类的技术来优化性能(例如,减小克隆对象的创建时间)和内存使用。
copy.deepcopy() 深副本,深副本就是原始对象的所有数据都被简单地复制到克隆对象中,没有例外。
在解释一下就是,如果copy的数据中有引用对象的内容,浅副本不会复制一个对象,而是将对象的引用值复制过来,减少循环的copy。深副本的话则会重新复制一个对象,存储新对象的地址。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。