原型模式
以前听过这样一句话:“程序员的最高境界就是Ctrl+C、Ctrl+V”,我们先不论这句话的对错,就论这个过程,这个过程我们都知道无非就是复制一个对象,然后将其不断地粘贴。这样的过程我们可以将其称之为“克隆”。再如我们应聘的时候打印了那么多的简历。
克隆我们都清楚,就是用一个物体复制若干个一模一样物体。同样,在面向对象系统中,我们同样可以利用克隆技术来克隆出若干个一模一样的对象。在应用程序中,有些对象比较复杂,其创建过程过于复杂,而且我们又需要频繁的利用该对象,如果这个时候我们按照常规思维new该对象,那么务必会带来非常多的麻烦,这个时候我们就希望可以利用一个已有的对象来不断对他进行复制就好了,这就是编程中的“克隆”。这里原型模式就可以满足我们的“克隆”,在原型模式中我们可以利用过一个原型对象来指明我们所要创建对象的类型,然后通过复制这个对象的方法来获得与该对象一模一样的对象实例。这就是原型模式的设计目的。
模式定义
通过前面的简单介绍我们就可以基本确定原型模式的定义了。所谓原型模式就是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
在原型模式中,所发动创建的对象通过请求原型对象来拷贝原型对象自己来实现创建过程,当然所发动创建的对象需要知道原型对象的类型。这里也就是说所发动创建的对象只需要知道原型对象的类型就可以获得更多的原型实例对象,至于这些原型对象时如何创建的根本不需要关心。
讲到原型模式了,我们就不得不区分两个概念:深拷贝、浅拷贝。
浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值,这个方式被称为浅拷贝。
深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。
对于深浅拷贝以前的文章介绍过
复制代码
角色
原型模式主要包含如下三个角色:
Prototype:抽象原型类。声明克隆自身的接口。
ConcretePrototype:具体原型类。实现克隆的具体操作。
Client:客户类。让一个原型克隆自身,从而获得一个新的对象。
复制代码
优点 1、如果创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率。
2、可以使用深克隆保持对象的状态。
3、原型模式提供了简化的创建结构。
缺点 1、在实现深克隆的时候可能需要比较复杂的代码。
2、需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事,必须修改其源代码,违背了“开闭原则”。
对于以上缺点python中有专门处理深克隆的方法deepcopy
模式使用场景 1、如果创建新对象成本较大,我们可以利用已有的对象进行复制来获得。
2、如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。 3、需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。
代码实现
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
大话设计模式
设计模式——原型模式
原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
原型模式是用场景:需要大量的基于某个基础原型进行微量修改而得到新原型时使用
"""
from copy import copy, deepcopy
# 原型抽象类
class Prototype(object):
def clone(self):
pass
def deep_clone(self):
pass
# 工作经历类
class WorkExperience(object):
def __init__(self):
self.timearea = ''
self.company = ''
def set_workexperience(self,timearea, company):
self.timearea = timearea
self.company = company
# 简历类
class Resume(Prototype):
def __init__(self,name):
self.name = name
self.workexperience = WorkExperience()
def set_personinfo(self,sex,age):
self.sex = sex
self.age = age
pass
def set_workexperience(self,timearea, company):
self.workexperience.set_workexperience(timearea, company)
def display(self):
print self.name
print self.sex, self.age
print '工作经历',self.workexperience.timearea, self.workexperience.company
def clone(self):
return copy(self)
def deep_clone(self):
return deepcopy(self)
if __name__ == '__main__':
obj1 = Resume('andy')
obj2 = obj1.clone() # 浅拷贝对象
obj3 = obj1.deep_clone() # 深拷贝对象
obj1.set_personinfo('男',28)
obj1.set_workexperience('2010-2015','AA')
obj2.set_personinfo('男',27)
obj2.set_workexperience('2011-2017','AA') # 修改浅拷贝的对象工作经历
obj3.set_personinfo('男',29)
obj3.set_workexperience('2016-2017','AA') # 修改深拷贝的对象的工作经历
obj1.display()
obj2.display()
obj3.display()
复制代码