【设计模式】原型模式

转换阵地,用《Mastering Python Design Patterns》来作指导。

clone()函数

# /usr/bin/python
# coding=utf-8


import copy


class A:
    def __init__(self):
        self.x = 18
        self.msg = 'Hello'


class B(A):
    def __init__(self):
        A.__init__(self)
        self.y = 34

    def __str__(self):
        return '{}, {}, {}'.format(self.x, self.msg, self.y)


if __name__ == '__main__':
    b = B()
    c = copy.deepcopy(b)
    print b
    print c
    print (b, c)
    print [i for i in str(b)]
    print [str(i) for i in (b, c)]
    print [i for i in (b, c)]
    print "%s"%c
    print "%s" % b

输出

18, Hello, 34
18, Hello, 34
(<__main__.B instance at 0x10d0edef0>, <__main__.B instance at 0x10d0edf38>)
['1', '8', ',', ' ', 'H', 'e', 'l', 'l', 'o', ',', ' ', '3', '4']
['18, Hello, 34', '18, Hello, 34']
[<__main__.B instance at 0x10d0edef0>, <__main__.B instance at 0x10d0edf38>]
18, Hello, 34
18, Hello, 34

Process finished with exit code 0
  • 方法str是一个特殊方法,它构造并返回PhoneNumber类的一个对象的字符串表示。解析器一旦遇到如下语句:
    print phone就会执行print phone.str()

  • 程序如果将PhoneNumber对象传给内建函数str(如str(phone)),或者为PhoneNumber对象使用字符串格式化运算符%(例如"%s"%phone),Python也会调用str方法

原型模式实现

当我们已有一个对象,并希望创建该对象的一个完整副本时,原型模式就派上用场了。在我们知道对象的某些部分会被变更但又希望保持原有对象不变之时,通常需要对象的一个副本。在这样的案例中,重新创建原有对象是没有意义的。
当我们想复制一个复杂对象时,使用原型模式会很方便。对于复制复杂对象,我们可以将对象当做是从数据库中获取的,并引用其他一些也是从数据库中获取的对象。若通过多次重复查询数据来创建一个对象,则要做很多的工作。在这种场景下使用原型模式要方便的多。

  • copy构造一个新的复合对象后,会尽可能地将在原始对象中找到的对象的引用插入新对象中
  • deepcopy构造一个新的复合对象后,会递归地将在原始对象中找到的对象的副本插入新对象中

两个版本的书有区别,也有大量的相似之处。如果知道两个版本的相似之处,可以先克隆一份,然后仅修改新版本与旧版本之间的不同之处。

# /usr/bin/python
# coding:utf-8

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, 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


class main():
    b1 = Book('The C programming Language', ('Brain 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'
    prototype.register(cid, b1)
    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()

输出

authors: ('Brain W. Kernighan', 'Dennis M.Ritchie')
length: 228
name: The C programming Language
price: 118$
publication_date: 1978-02-22
publisher: Prentice Hall
tags: ('C', 'programming', 'algorithms', 'data structures')

authors: ('Brain W. Kernighan', 'Dennis M.Ritchie')
edition: 2
length: 274
name: The C Programming Language(ANSI)
price: 48.99$
publication_date: 1988-04-01
publisher: Prentice Hall
tags: ('C', 'programming', 'algorithms', 'data structures')

ID b1 : 4340495568 != ID b2 : 4340690096

Process finished with exit code 0
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 定义 原型模式是一个创建型的设计模式。用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式多用于...
    忘尘无憾阅读 556评论 0 0
  • 前言 Android的设计模式系列文章介绍,欢迎关注,持续更新中: Android的设计模式-设计模式的六大原则一...
    四月葡萄阅读 5,620评论 4 10
  • 目录 本文的结构如下: 引言 什么是原型模式 浅克隆和深克隆 clone() 模式的结构 典型代码 代码示例 优点...
    w1992wishes阅读 575评论 0 0
  • 原型模式 介绍 在许多面向对象的应用程序中,有些对象的创建代价过大或者过于复杂。要是可以重建相同的对象并作轻微的改...
    666真666阅读 480评论 0 2
  • 1. 跟老S吃了顿饭,聊起他的感情故事,又联想起现代人的爱情观,突然有点惶恐。拥有一份稳定,合适的爱怎么如此之难。...
    鲸鱼和梦阅读 316评论 0 0