原型模式(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。深副本的话则会重新复制一个对象,存储新对象的地址。

下集预告 (适配器模式)


neilliu
59 声望9 粉丝

coder is coding code snippet,coder change the world!