原型模式(Prototype)

原型模式(Prototype)

原型模式(Prototype)

意图:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。

应用:Java/C#中的Clonable和IClonable接口等。

模式结构

心得

原型模式本质上就是对象的拷贝,使用对象拷贝代替对象创建的原因有很多。比如对象的初始化构造非常复杂,消耗资源巨大;运行时对象状态变化不可重现;无法获得对象的成员的运行时值等。实现原型模式关键在于对象的正确复制,因此像高级语言实现的那样——支持复制接口。而对象的复制分为“深复制”和“浅复制”,前者除了复制对象本身数据外,还需要复制对象内指针引用的数据,后者则是仅仅复制对象数据。另外,深度复制如果遇到循环引用的对象就会产生问题。

举例

按照上述设计,这里实现模式的代码如下:

//基本原型接口——相当于Clonable
class Prototype
{
public:
 virtual Prototype* Clone()=0;
 virtual ~Prototype(){}
};
//原型管理器
class PrototypeMgr
{
    hash_map<char*,Prototype*>map;
public:
 void regProto(char* key,Prototype*p)
    {
 if(map.find(key)!=map.end())
        {
            delete map[key];
        }
        map[key]=p;
    }
    Prototype* const operator[](char* key)
    {
 if(map.find(key)!=map.end())
        {
 return map[key]->Clone();
        }
 else
 return NULL;
    }
    ~PrototypeMgr()
    {
 for(hash_map<char*,Prototype*>::iterator it=map.begin();
            it!=map.end();++it)
        {
            delete it->second;
        }
    }
};
//浅拷贝
class ConcretePrototype1:public Prototype
{
 int * refMember;
 int member;
public:
 virtual Prototype* Clone()
    {
        cout<<"执行ConcretePrototype1的浅复制"<<endl;
        ConcretePrototype1*copy= new ConcretePrototype1;
        copy->member=member;
        copy->refMember=refMember;
 return copy;
    }
};
//深度拷贝
class ConcretePrototype2:public Prototype
{
 int * refMember;
 int member;
public:
    ConcretePrototype2():refMember(new int){}
 virtual Prototype* Clone()
    {
        cout<<"执行ConcretePrototype2的深复制"<<endl;
        ConcretePrototype2*copy= new ConcretePrototype2;
        copy->member=member;
        copy->refMember=new int;//指针引用数据也要拷贝
        *copy->refMember=*refMember;
 return copy;
    }
 virtual~ConcretePrototype2()
    {
        delete refMember;
    }
};

这里添加一个原型管理器,用来管理所有的注册的原型。用户需要拷贝出原型只需要从这里请求即可。

PrototypeMgr mgr;
//注册原型
mgr.regProto("浅复制",new ConcretePrototype1);
mgr.regProto("深复制",new ConcretePrototype2);
//请求原型
Prototype*cp1=mgr["浅复制"];
Prototype*cp2=mgr["深复制"];
delete cp1;
delete cp2;

参考文章http://zxyjxnu.blog.163.com/blog/static/1330787122007103095839612/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IMWeb前端团队

JS中的非可变性

非可变性是函数式编程的一个核心规则,对于面向对象编程也有很多用处。本文为参考sitepoint(参考链接1)中的文章后所记录的一些主要内容。 参考链接1:...

20350
来自专栏C语言及其他语言

【每日一题】问题 1209: 密码截获

题目描述 Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码 进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或...

28870
来自专栏不会写文章的程序员不是好厨师

浅析HystrixRollingNumber(用于qps计数的数据结构)

考虑到一种需求场景,我们需要统计系统qps、每秒平均错误率等。qps表示每秒的请求数目,能想到的最简单的方法就是统计一定时间内的请求总数然后除以总统计时间,所以...

34920
来自专栏C语言及其他语言

【每日一题】问题 1209: 密码截获

Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码 进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一...

16520
来自专栏xiaoxi666的专栏

【左神算法课】子数组最大差值小于某阈值,求满足条件的子数组个数

  1.从第一个元素开始依次向后遍历,同时维护两个窗口(由于要同时操作窗口的头部和尾部,故采用双端队列):

19020
来自专栏互联网技术栈

并发编程- java.util.concurrent用户指南

本指南根据 Jakob Jenkov 最新博客翻译,请随时关注博客更新:http://tutorials.jenkov.com/java-util-concur...

13530
来自专栏IMWeb前端团队

ES6学习之函数传参

本文作者:IMWeb Terrance 原文出处:IMWeb社区 未经同意,禁止转载 ECMAScript 6 (or ECMAScript 201...

263100
来自专栏JavaEdge

分析Java AtomicIntegerincrementAndGet方法缺点

70550
来自专栏日常分享

Java 循环队列的实现

  队列(Queue)是限定只能在一端插入、另一端删除的线性表。允许删除的一端叫做队头(front),允许插入的一端叫做队尾(rear),没有元素的队列称为“空...

28230
来自专栏xingoo, 一个梦想做发明家的程序员

汇编语言 手记8

栈有两个基本的操作:入栈和出栈 入栈:将一个新的元素放到栈顶 出栈:从栈顶取出一个元素 栈顶的元素总是最后入栈,需要出栈时,又最先被从栈中取出。 栈的操作规则:...

20350

扫码关注云+社区

领取腾讯云代金券