相信大多数的人都看过《西游记》,对孙悟空拔毛变出小猴子的故事情节应该都很熟悉。孙悟空可以用猴毛根据自己的形象复制出很多跟自己一模一样的小猴兵出来,其实在设计模式中也有一个类似的模式,我们可以通过一个原型对象来克隆出多个一模一样的对象,这个模式就是原型模式。

一 大同小异的工作周报

  M公司一直在使用自行开发的一个OA系统进行日常工作办理,但在使用过程中,越来越多的人对工作周报的创建和编写模块产生了抱怨。追其原因,M公司的OA管理员发现,由于某些岗位每周工作存在重复性,工作周报内容都大同小异,如下图所示:

  这些周报只有一些小地方存在差异,但是现行系统每周默认创建的周报都是空白报表,因此用户只能通过重新输入或不断地复制与粘贴来填写重复的周报内容,极大地降低了工作效率,浪费宝贵的时间。如何快速创建相同或者相似的工作周报,成为了M公司软件开发人员的一个新问题。

  M公司开发人员经过分析,决定按照以下思路对工作周报模块进行重新设计:

  (1)除了允许用户创建新周报外,还允许用户将创建好的周报保存为模板(也就是原型)。

  (2)用户在再次创建周报时,可以创建全新的周报,还可以选择合适的模板复制生成一个相同的周报,然后对新生成的周报根据实际情况进行修改,产生新的周报。

二 原型模式概述

2.1 关于原型模式

  原型模式的原理很简单,将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象克隆自己来实现创建过程。

原型模式(Prototype):使用原型实例指定创建对象的种类,并且通过拷贝这些原 型创建新的对象。原型模式是一种对象创建型模式。

  需要注意的是,通过克隆方法所创建的对象时全新的对象。

2.2 类图

  

2.3 代码实现

2.3.1 抽象克隆类

class AbstractClone
{
protected:
AbstractClone()
{
//cout << "AbstractClone Construct" << endl;
} public:
~AbstractClone()
{
//cout << "AbstractClone Deconstruct" << endl;
} virtual AbstractClone* Clone() = ;
virtual void PrintWeekly() = ;
};

2.3.2 周报类

class CWeeklyClone : public AbstractClone
{
public:
/*CWeeklyClone()
{
cout << "CWeeklyLogClone Construct" << endl;
}*/ CWeeklyClone(string strName="", string strDate="", string strContent="", CAttachment *pAttachment=NULL)
{
//cout << "CWeeklyLogClone Construct" << endl; m_strName = strName;
m_strDate = strDate;
m_strContent = strContent;
if (pAttachment!= NULL)
{
m_pAttachment = new CAttachment(*pAttachment);
}
else
{
m_pAttachment = NULL;
} }
CWeeklyClone(CWeeklyClone& other)
{
// 拷贝构造函数需要注意深拷贝和浅拷贝的问题
m_strName = other.m_strName;
m_strDate = other.m_strDate;
m_strContent = other.m_strContent; if (other.m_pAttachment != NULL)
{
// 浅拷贝方式
// m_pAttachment = other.m_pAttachment;
// 深拷贝方式
m_pAttachment = new CAttachment(*other.m_pAttachment); }
else
{
m_pAttachment = NULL;
}
//cout << "CWeeklyClone CopyConstruct" << endl;
} ~CWeeklyClone()
{
if (m_pAttachment != NULL)
{
delete m_pAttachment;
m_pAttachment = NULL;
}
//cout << "CWeeklyLogClone Deonstruct" << endl;
} CWeeklyClone* Clone()
{
return new CWeeklyClone(*this);
} void SetName(string strName)
{
m_strName = strName;
} void SetDate(string strDate)
{
m_strDate = strDate;
}
void SetContent(string strContent)
{
m_strContent = strContent;
}
void SetAttachment(CAttachment *pAttachment)
{
if (m_pAttachment != NULL)
{
m_pAttachment = pAttachment;
}
}
CAttachment *GetAttachment()
{
return m_pAttachment;
}
void PrintWeekly()
{
cout << "start:------------M公司个人工作周报------------" << endl;
cout << "周次:" << m_strDate <<endl;
cout << "员工:" << m_strName <<endl;
cout << "内容:" << m_strContent << endl;
if (m_pAttachment != NULL)
cout << "附件:" << m_pAttachment->m_strContent << endl; cout << "end:------------M公司个人工作周报------------" << endl;
}
private:
string m_strName;
string m_strDate;
string m_strContent; CAttachment *m_pAttachment;
};

2.3.3 附件类

#include <string>
#include <iostream>
using namespace std; // 附件类
class CAttachment
{
public:
CAttachment(string strContent="")
{
m_strContent = strContent;
//cout << "CAttachment CopyConstruct" << endl;
}
CAttachment(CAttachment &other)
{
m_strContent = other.m_strContent;
//cout << "CAttachment CopyConstruct" << endl;
}
~CAttachment()
{
//cout << "CAttachment Deonstruct" << endl;
} public:
string m_strContent;
};

2.4 测试

#include "stdio.h"

#include "prototype.h"

void main()
{
// 创建附件
CAttachment *pAttachment = new CAttachment("附件:紫贝龙二号文件"); // 创建周报
CWeeklyClone *pWeekly1 = new CWeeklyClone("张林", "第一周", "ddcpy模块单元测试", pAttachment);
pWeekly1->PrintWeekly(); CWeeklyClone *pWeekly2 = pWeekly1->Clone();
pWeekly2->SetDate("第二周");
pWeekly2->PrintWeekly(); // 判断周报是否相同
cout << "深拷贝模式下判断周报和附件是否相同:" << endl;
pWeekly1==pWeekly2 ? (cout << "周报相同"<< endl):(cout << "周报不相同" << endl);
pWeekly1->GetAttachment()==pWeekly2->GetAttachment() ? (cout << "附件相同"<< endl):(cout << "附件不相同" << endl);
return;
}

三 原型模式总结

3.1 主要优点

  (1)当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,通过复制一个已有的实例可以提高新实例的创建效率。

  (2)可以使用深复制的方式保存对象的状态。将对象复制一份并将其状态保存起来,以便于在使用的时候使用,比如恢复到某一个历史状态,可以辅助实现撤销操作。

3.2 主要缺点

  (1)需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了开闭原则

  (2)为了支持深复制,当对象之间存在多重嵌套引用关系时,每一层对象都必须支持深复制,实现起来可能比较麻烦。

3.3 应用场景

  最主要的应用场景就在于 创建新对象成本较大(例如初始化需要占用较长的时间,占用太多的CPU资源或者网络资源),新的对象可以通过原型模式对已有对象进行复制来获得。如果是相似对象,则可以对其成员变量稍作修改。

设计模式之原型(prototype)模式的更多相关文章

  1. 设计模式C++描述----08.原型(Prototype)模式

    一. 概述 定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 换句话说,就是不用重新初始化对象,而是动态地获得对象运行时的状态. 再说明白点,就是要一个拷贝过构造函数类似功能的接 ...

  2. Java 实现原型(Prototype)模式

    public class BaseSpoon implements Cloneable {//spoon 匙, 调羹 String name; public String getName() { re ...

  3. 原型(Prototype)模式

    原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是原型模式的用意.原型模式的结构 原型模式要求对象实现一个可以“克隆 ...

  4. 设计模式--原型(Prototype)模式

    写这些也许有人认为“为了模式而模式”.Insus.NET所想到的,每个大师成为大师之前,也许都得这样做. 走路,从小就开始学,直至现在,谁还不是为了走路而走路?一直重复着...... 很多人没有分享自 ...

  5. 六、原型(Prototype)模式

    原型模式是对象的创建模式,通过给出一个原型对象来指明所要创建的对象的类型.然后用复制这个原型对象的方法来创建出更多同类型的对象. 原型模式可以不用重新初始化对象,而动态的获取对象运行时的状态.使用原型 ...

  6. 克隆复制可使用原型( Prototype)设计模式

    今天有学习设计模式的原型(Prototype)<设计模式--原型(Prototype)模式>http://www.cnblogs.com/insus/p/4152773.html .为了加 ...

  7. 设计模式_11_原型模式(prototype)深拷贝、浅拷贝

    设计模式_11_原型模式(prototype) 浅拷贝: package designPatternOf23; /** * 定义:用原型实例,指定创建对象的种类,并通过拷贝这些原型创建新的对象 * P ...

  8. [设计模式] 4 原型模式 prototype

    设计模式:可复用面向对象软件的基础>(DP)本文介绍原型模式和模板方法模式的实现.首先介绍原型模式,然后引出模板方法模式. DP书上的定义为:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...

  9. 乐在其中设计模式(C#) - 原型模式(Prototype Pattern)

    原文:乐在其中设计模式(C#) - 原型模式(Prototype Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 原型模式(Prototype Pattern) 作者:weba ...

  10. C#设计模式之六原型模式(Prototype)【创建型】

    一.引言 在开始今天的文章之前先说明一点,欢迎大家来指正.很多人说原型设计模式会节省机器内存,他们说是拷贝出来的对象,这些对象其实都是原型的复制,不会使用内存.我认为这是不对的,因为拷贝出来的每一个对 ...

随机推荐

  1. hadoop单击模式环境搭建

    一 安装jdk 下载相应版本的jdk安装到相应目录,我的安装目录是/usr/lib/jdk1.8.0_40 下载完成后,在/etc/profile中设置一下环境变量,在文件最后追加如下内容 expor ...

  2. Apache 工作模式详解

    Apache 工作模式详解 Apache 2.X  支持插入式并行处理模块,称为多路处理模块(MPM).在编译apache时必须选择也只能选择一个MPM,对类UNIX系统,有几个不同的MPM可供选择, ...

  3. Linux 下的 core dump

    core dump 的基本概念      当一个进程要异常终止时 ,可以选择把进程的用户空间内存数据全部保存到磁盘上 ,文件名通常是 core, 这叫做 Core Dump.通常情况下,core文件会 ...

  4. 《Python学习手册》(二)

    <Python学习手册>(二) --类型和运算 数字 十六进制 八进制 二进制 0x 0o 0b hex() oct() bin() >>>int('10',2) 2 & ...

  5. C++ vector 多次删除第一个元素

    转载声明: 代码都是来源于一下连接,做了一点点修改,为了记忆方便,故贴在这里,原文链接:http://blog.csdn.net/doctor_feng/article/details/1188078 ...

  6. spark学习12(spark架构原理)

    spark采用的是主从式的架构,主节点叫master,从节点是worker Driver 我们编写的spark就在Driver上,由driver进程执行. Driver是spark集群的节点之一,或你 ...

  7. windchill系统——一些功能查找

    1.创建产品 导航栏的浏览——>最近的产品——>全部查看——>新建产品——>填写“名称”.选择“模板”.一定的“说明”.“专用访问权限”一般选择“否”——>“确定”选项 ...

  8. Jar 包 及运行Jar包 - 转载

    Eclipse的jar file和Runnable JAR file的区别 - 及bat运行Runnable JAR文件 1.两种jar的区别 jar file是最普通的jar包,即平时我们工程中li ...

  9. NumPy Matplotlib库

    NumPy - Matplotlib Matplotlib 是 Python 的绘图库. 它可与 NumPy 一起使用,提供了一种有效的 MatLab 开源替代方案. 它也可以和图形工具包一起使用,如 ...

  10. 如何让Myeclipse已经关闭掉的项目不显示出来

    一.打开Package Explorer视图,在它的右上角有一个向下的三角图标. 2.点击后选择Filters,在弹出的Filter配置窗口中选中"Closed Projects" ...