####零、原型模式
- 什么是原型模式:
原型模式无非就是克隆一个对象,其最简单的形式就是一个 clone() 函数,接受一个对象作为输入参数,返回输入对象的一个副本。在 Python 中可以使用 copy.deepcopy() 函数来完成。
- 什么是副本:
一个对象在 某一时间点 的 完全 复制,时间是一个重要元素,因为它会影响克隆所包含的内容。
- 引用和副本间的区别:
如果A和B都持有同一个对象的引用,那么A修改对象后,B就能看到对象的修改,反之亦然。
如果A和B都持有一个对象的副本,呢么A修改所持有的副本,B是看不到修改的,反之亦然。因为A和B所持有的副本是两个独立的内存地址。
####一、身边的例子
- 细胞的分裂。细胞核分裂产生两个新的细胞核,这两个细胞都具有原来细胞相同的染色体、DNA等。
- VTK(可视化工具套件)。VTK是一个开源的跨平台的系统,用于三位计算图形和图片处理以及可视化。VTK利用原型模式来创建几何元素。
- Python中很多应用也都使用了原型模式。
####二、什么情况下使用
- 当我们已有一个对象,并希望创建该对象的一个完整副本时;
- 在我们知道对象的某些本分会被改变,但有希望保持原有的对象不变时;
- 我们想复制一个复杂的对象时。
####三、应用案例
下面我们来看一个案例,利用原型模式展示一个图书的各个版本信息
import copy from collections import OrderedDict class Book: def __init__(self, name, authors, price, **rest): '''rest的例子有:出版商、长度、标签、出版日期''' self.name = name self.authors = authors self.price = price self.__dict__.update(rest) def __str__(self): mylist = [] 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: def __init__(self): self.objects = dict() def register(self, identifiter, obj): self.objects[identifiter] = 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 Cprogramming Language', ('Brian W.Kernighan', 'Dennis M.Ritchie'), price=118, publisher='Prentice Hall', length=228, publication_date='1978-02-22', tags=('C', 'programming', 'algorithma', 'algorihma', 'data structures')) prototype = Prototype() cid = 'k&r-first' prototype.register(cid, b1) b2 = prototype.clone(cid, name='The CProgramming 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()