设计模式之原型模式

一、理解原型模式

   原型模式就是帮助创建对象的克隆,有时候需要在对象的副本上进行操作,这样不会改变原对象的变量。假如figt和lice是两位厨师,现在figt有一份关于红烧肉的配料,他想分享给lice,那么如果lice想在配料谱上做修改,是否figt拿到的也会跟着变呢?

  如果是上图这样的表示figt与lice对同一个配料谱的引用,如果lice做了修改,figt看到的就是修改过后的内容,而且修改的时间不同,内容可能也会不同。但是这是不希望看到的,lice应该拥有figt的副本,这样修改自己的对figt没有影响。

如上所示,这样lice就拥有自己的副本了,随意修改,不影响figt。在python中可以通过copy.deepcopy来完成。

二、原型模式的实现

import copy
class A:

    def __init__(self):
        self.x=3

if __name__=="__main__":
    a=A()
    b=copy.deepcopy(a)
    print(a)
    print(b)
    
##################输出###########
#<__main__.A object at 0x00000000004F6828>
#<__main__.A object at 0x00000000004F68D0>

使用deepcopy函数算是比较简单的完成原型模式,可以看到两个对象的地址不同,说明已经完成了a对象的副本了。

三、应用案例

 现在新建一个书籍相关的类,并且创建对象,然后利用这个对象再创建一个副本,并且可以在副本上进行修改。

from collections import OrderedDict
import time, hashlib
class Book:

    def __init__(self,name,authors,price,**kwargs):
        """
        :param name:
        :param authors:
        :param price:
        :param kwargs: 出版商、出版日期等,关键词的形式(名称=值)传入更多的参数
        """
        self.name=name
        self.authors=authors
        self.price=price
        self.__dict__.update(kwargs)


    def create(self):
        """
        给自己对象创建一个唯一id
        :return:
        """
        m = hashlib.md5()
        m.update(bytes(str(time.time()), encoding="utf-8"))
        return m.hexdigest()


    def __str__(self):
        list=[]
        ordered = OrderedDict(sorted(self.__dict__.items())) #每次打印出对象的内容不会改变顺序
        for i in ordered.keys():
            list.append("%s:%s"%(i,ordered[i]))
            if i=="price":
                list.append("$")
            list.append("
")
        return "".join(list)

然后再创建一个专门用于clone的类Prototype

import copy
class Prototype:

    def __init__(self):

        self.objects=dict()

    def register(self,identifier,obj):
        self.objects[identifier]=obj

    def unregister(self,identifier):
        del self.objects[identifier] #删除对象的引用,触发析构方法__del__

    def clone(self,identifier,**attr): #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

然后可以进行实例以及调用方法

b1=Book("Python设计","Bjg",20,pub_date="2018-03-01") #实例化Book类
b1_id=b1.create()#生成b1对象id

prototype=Prototype()
prototype.register(b1_id,b1) #将对象与id进行绑定

b2=prototype.clone(b1_id,edition=3) #获取b1的副本,并且对副本进行了修改,添加edition=3

print(b1)
print(b1.__dict__)
print(b2)
print(b2.__dict__)
######################输出###############
# authors:Bjg
# name:Python设计
# price:20$
# pub_date:2018-03-01
#
# {'price': 20, 'name': 'Python设计', 'pub_date': '2018-03-01', 'authors': 'Bjg'}


# authors:Bjg
# edition:3
# name:Python设计
# price:20$
# pub_date:2018-03-01
#
# {'edition': 3, 'name': 'Python设计', 'authors': 'Bjg', 'pub_date': '2018-03-01', 'price': 20}

 参考:精通Python设计模式一书

原文地址:https://www.cnblogs.com/shenjianping/p/11093220.html