首页 > 设计模式 之美 -- 原型模式

设计模式 之美 -- 原型模式

文章目录

        • 1. 解决问题
        • 2. 应用场景
        • 3. 实现方式
          • C++实现
          • C语言实现
        • 4. 缺点
        • 5. 和其他三种创建模式的对比(单例,工厂,建造者)

1. 解决问题

如果对象的创建成本较大,而同一个类的不同对象之间的差别不大(大部分字段相同),在这种情况下,我们可以利用已有对象(原型)进行赋值(拷贝)的方式,创建新的对象,从而达到节省对象创建时间的目的。

2. 应用场景

  • 需要在运行过程中,动态的拷贝一份对象
  • 需要某个对象在某个状态下的副本
  • 处理一些简单对象时,对象之间的差别很小,且重建代价比较大
  • 使用对象时,如果对象的构造参数很多,自己又不能完全确定参数含义,这个时候使用该模式就可以省去了解参数的过程,直接使用原型模式获得同样的对象即可

3. 实现方式

浅拷贝:只会复制对象中基本数据类型数据和引用对象的内存地址,不会递归的复制引用对象,以及引用对象的引用对象。浅拷贝 存在数据被修改的风险,会导致场景变得复杂多变。

深拷贝:得到一份完完全全的独立对象,深拷贝比起浅拷贝更加耗时,耗内存。深拷贝更加安全,拷贝出来的独立的对象不影响其他的对象。

C++实现

实现功能:一个简单的原型模式,clon成员函数 用来创建当前类的实例。

#include 
#include 
#include using namespace std;class Create_Prototype{ 
public:Create_Prototype():value(6){ m_time = time((time_t*)NULL);	}Create_Prototype(Create_Prototype &cp){ //普通的拷贝构造,仅仅拷贝当前对象的基本数据类型的数据和引用对象的内存地址。(浅拷贝)this -> value=cp.value;this -> m_time = time((time_t*)NULL);}int get_value(){  return this -> value;}Create_Prototype *clon(){ return new Create_Prototype(*this);//使用的是new的方式,会分配新的对象空间(深拷贝)}time_t m_time;int value;
};int main()
{ Create_Prototype *object = new Create_Prototype();cout <<"value is :" << object->value << " time is : " << object->m_time <<endl;sleep(3);/*原型模式创建对象 -- 深拷贝*/Create_Prototype *cp_object = object->clon();/*普通的拷贝构造 -- 浅拷贝*///Create_Prototype *cp_object = object; //最后的输出会出现异常cout <<"value is :" << cp_object->value << " time is : " << cp_object->m_time <<endl;cout << "obj address is: " << object << " value address is : " << &(object->value) << endl;cout << "cp_obj address is: " << cp_object << " value address is : " <<&(cp_object->value) << endl;delete object;delete cp_object;return 0;
}

执行输出如下:

浅拷贝会抛出异常(可以看到如下输出,两个对象指向同一块内存地址,最终该内存区域会释放两次,导致异常)

value is :6 time is : 1587708400
value is :6 time is : 1587708400
obj address is: 0x1eb7010 value address is : 0x1eb7018
cp_obj address is: 0x1eb7010 value address is : 0x1eb7018
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001eb7010 ***

深拷贝(原型模式创建的对象)正常输出,且每个对象有自己独立的内存地址

value is :6 time is : 1587708436
value is :6 time is : 1587708439
obj address is: 0x14b8010 value address is : 0x14b8018
cp_obj address is: 0x14b8030 value address is : 0x14b8038
C语言实现

实现功能:

动态复制一个osd信息结构

1、带有copy功能的 copy函数指针

2、copy函数实现

#include 
#include 
#include typedef struct OSD_INFO{ int osd_id;int osd_type;char osd_name[16];struct OSD_INFO *(*copy)(struct OSD_INFO *);//copy函数指针
}Osd_Info;/*可以使用该原型操作,消耗很短的时间来构造大量的同类型的对象*/
struct OSD_INFO *copy_osd_info(struct OSD_INFO *osd_info)
{ struct OSD_INFO *tmp_osd_info = (struct OSD_INFO *)malloc(sizeof(struct OSD_INFO));if (tmp_osd_info == NULL){ return NULL;}memmove(tmp_osd_info,osd_info,sizeof(struct OSD_INFO));return tmp_osd_info;
}int main()
{ struct OSD_INFO osd_info = { 0};struct OSD_INFO *other_osd = NULL;osd_info.osd_id = 1;osd_info.osd_type = 0;strcpy(osd_info.osd_name,"osd.1");osd_info.copy = copy_osd_info;other_osd = osd_info.copy(&osd_info);//原型模式 构造一个新的结构体变量printf("osd id is:%d
",other_osd->osd_id);printf("osd type is:%d
",other_osd->osd_type);printf("osd name is:%s
",other_osd->osd_name);if(other_osd != NULL){ free(other_osd);}return 0;
}

输出如下:

osd id is:1
osd type is:0
osd name is:osd.1

4. 缺点

  1. 在有继承相关的类图中,每个子类都需要实现一个clon函数,如果是新类则只需扩展接口,但已有的类则需修改内部源码,违反开闭原则
  2. 实现深拷贝的时候,如果初始化成员列表较多,则实现会比较复杂

5. 和其他三种创建模式的对比(单例,工厂,建造者)

单例模式:

在特定模式下(日志系统),一个类仅允许创建一个实例

工厂模式:

创建拥有相关性的不同对象(继承同一父类或者接口的子类),由给定的参数来决定创建哪一种类的对象

建造者模式:

创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。

原型模式:

快速创建对象,针对部分实例化成本较大的类,且该类需要频繁实例化时使用原型模式更为格式。

更多相关:

  • 混合osd的部署 先部署所有的ssd 在/etc/ceph.conf中最后添加ssd做osd的block大小如下: 比如部署中有两个ssd,则添加 [osd.0] bluestore_block_size = xxxx [osd.1] bluestore_block_size = xxx 如上的size大小计算如下,如ssd容量...

  • 文章目录Pool创建ec pool创建副本pool创建Pool参数创建根故障域及添加osd其他命令Tier相关 Pool创建 ec pool创建 创建profile ceph osd erasure-code-profile set $profile_name k=$k m=$m crush-failure-domain...

  • 文章目录简介使用OSD相关操作PG相关操作对象相关操作总结 简介 ceph-objectstore-tool工具,能够操作到ceph最底层的数据,包括pg,对象层级。它能够对底层pg以及对象相关数据进行获取、修改。并能够对一些问题pg和对象进行简单修复。所以使用该工具进行操作的时候需要谨慎(涉及到修改的操作最好备份一份数据)...

  • 文章目录ceph版本:环境配置:异常问题:问题解决:总结 ceph版本: ceph 12.2.1 环境配置: tier_pool 16个分区大小800G 的osd容量 3副本 data_pool 32个4T盘 3副本 异常问题: ps:在分布式存储中遇到任何问题都不要先去通过重设存储节点,清除磁盘数据来解决,一定要...

  • 转自:http://stackoverflow.com/questions/8377091/what-are-the-differences-between-cv-8u-and-cv-32f-and-what-should-i-worry-about CV_8U is unsigned 8bit/pixel - ie a pixel...