专栏首页技术点滴原型模式(Prototype)

原型模式(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 条评论
登录 后参与评论

相关文章

  • 远程线程注入引出的问题

    远程线程注入引出的问题 一、远程线程注入基本原理 远程线程注入——相信对Windows底层编程和系统安全熟悉的人并不陌生,其主要核心在于一个Windows AP...

    Florian
  • 那些陌生的C++关键字

    那些陌生的C++关键字 学过程序语言的人相信对关键字并不陌生。偶然间翻起了《C++ Primer》这本书,书中列举了所有C++的关键字。我认真核对了一下,竟然发...

    Florian
  • 单例模式(Singleton)

    单例模式(Singleton) 单例模式(Singleton) 意图:保证一个类只有一个实例,并提供一个访问它的全局访问点。 应用:Session或者控件的唯一...

    Florian
  • 如何应用HTTPDNS及全站HTTPS协议避免域名被劫持?

    域名对于公司重要吗?毋庸置疑的当然是很重要,域名就相当于一个门牌号,如果您去拜访别人,不知道门牌,是不是很耽误事呢?那么域名被劫持的可能性有哪几种呢?

    墨者盾
  • 转--Golang语言--复合数据

    1、array 数组的类型格式为单个数据单元类型+长度构成,如 [2]int,其中 [2] 代表数组的长度,而 int 代表每个单元都是整形。 数组的元素操作也...

    李海彬
  • PE解析器的编写(四)——数据目录表的解析

    在PE结构中最重要的就是区块表和数据目录表,上节已经说明了如何解析区块表,下面就是数据目录表,在数据目录表中一般只关心导入表,导出表和资源这几个部分,但是资源实...

    Masimaro
  • yii常用操作

    yii 数据save后得到插入id $post->save(); //得到上次插入的Insert id $id = $post->attributes['id'...

    wangxl
  • NodeJs-Lesson1-require和module.exports探究

    这里的两种方法都能导出该模块,并且,将该模块导出到一个对象当中 此处你是否有疑问呢?为何两个东西会导出到一个对象当中,还是说这两个对象是同一个对象呢?

    envoke
  • 【生活现场】从打牌到map-reduce工作原理解析

    找到工作后的一小段时间是清闲的,小史把新租房收拾利索后,就开始找同学小赵,小李和小王来聚会了。

    乔戈里
  • HashMap 的 7 种遍历方式与性能分析!(强烈推荐)

    随着 JDK 1.8 Streams API 的发布,使得 HashMap 拥有了更多的遍历的方式,但应该选择那种遍历方式?反而成了一个问题。

    Java中文社群-磊哥

扫码关注云+社区

领取腾讯云代金券