设计模式 之美 -- 原型模式
文章目录
- 1. 解决问题
- 2. 应用场景
- 3. 实现方式
- C++实现
- C语言实现
- 4. 缺点
- 5. 和其他三种创建模式的对比(单例,工厂,建造者)
1. 解决问题
如果对象的创建成本较大,而同一个类的不同对象之间的差别不大(大部分字段相同),在这种情况下,我们可以利用已有对象(原型)进行赋值(拷贝)的方式,创建新的对象,从而达到节省对象创建时间的目的。
2. 应用场景
- 需要在运行过程中,动态的拷贝一份对象
- 需要某个对象在某个状态下的副本
- 处理一些简单对象时,对象之间的差别很小,且重建代价比较大
- 使用对象时,如果对象的构造参数很多,自己又不能完全确定参数含义,这个时候使用该模式就可以省去了解参数的过程,直接使用原型模式获得同样的对象即可
3. 实现方式
浅拷贝:只会复制对象中基本数据类型数据和引用对象的内存地址,不会递归的复制引用对象,以及引用对象的引用对象。浅拷贝 存在数据被修改的风险,会导致场景变得复杂多变。
深拷贝:得到一份完完全全的独立对象,深拷贝比起浅拷贝更加耗时,耗内存。深拷贝更加安全,拷贝出来的独立的对象不影响其他的对象。
C++实现
实现功能:一个简单的原型模式,clon成员函数 用来创建当前类的实例。
#include <iostream>
#include <ctime>
#include <unistd.h>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 <stdio.h>
#include <string.h>
#include <stdlib.h>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\n",other_osd->osd_id);printf("osd type is:%d\n",other_osd->osd_type);printf("osd name is:%s\n",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. 缺点
- 在有继承相关的类图中,每个子类都需要实现一个clon函数,如果是新类则只需扩展接口,但已有的类则需修改内部源码,违反开闭原则
- 实现深拷贝的时候,如果初始化成员列表较多,则实现会比较复杂
5. 和其他三种创建模式的对比(单例,工厂,建造者)
单例模式:
在特定模式下(日志系统),一个类仅允许创建一个实例
工厂模式:
创建拥有相关性的不同对象(继承同一父类或者接口的子类),由给定的参数来决定创建哪一种类的对象
建造者模式:
创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。
原型模式:
快速创建对象,针对部分实例化成本较大的类,且该类需要频繁实例化时使用原型模式更为格式。
相关文章:

Objective-C语法简记
开始学习iPhone开发了,虽然现在已经有了Swift,但我还是老老实实地学习Objective-C,鄙人入门的程序语言是C,后来学习了C#和Java,现在来学Objective-C,这篇只是一些很简略的笔记,不算是语法书。 代…

java编写最大公约数_Java编写最大公约数和最小公倍数
package javaapplication24;class NegativeIntegerException extends Exception{String message;public NegativeIntegerException(){message"方法的参数值不是正整数";}public String toString(){return message;}}class MaxCommonDivisor{public int getMaxCommonD…
肤色检测算法 - 基于不同颜色空间简单区域划分的皮肤检测算法
由于能力有限,算法层面的东西自己去创新的很少,很多都是从现有的论文中学习,然后实践的。 本文涉及的很多算法,在网络上也有不少同类型的文章,但是肯定的一点就是,很多都是不配代码的,或者所附带…

【算法学习】堆排序建立最大堆
本文代码均转自: 作者:早就戒了 来源:CSDN 原文:https://blog.csdn.net/qq_37169817/article/details/79777264 版权声明:本文为博主原创文章,转载请附上博文链接! 1 public class HeapSort { 2…

设计模式 之美 -- 代理模式
文章目录1. 解决问题2. 应用场景1. 业务系统的非功能性开发2. 代理模式在RPC、缓存中的应用3. 实现C实现C语言实现1. 解决问题 客户端和目标对象之间需要进行交互,此时客户端类和目标对象类相关操作之间的逻辑如果交合在一起,会导致客户端和目标对象模块…

java中注解的使用_java中注解的使用
使用过ssh框架的人一定也使用过注解,尤其是在spring框架中,注解可谓是spring容器和AOP编程的重要环节。注解就是用于修饰类、全局变量、方法、参数或局部变量的接口,java中规定,注解的使用不允许影响其修饰类的存在,也…

水题/poj 1852 Ants
1 /*2 PROBLEM:poj18523 AUTHER:Nicole4 MEMO:水题5 */6 #include<cstdio>7 using namespace std;8 int cmax(int a,int b){return a>b?a:b;}9 int cmin(int a,int b){return a<b?a:b;} 10 int main() 11 { 12 int cases; 13 scanf("%d…

素数、最大公约数、最下公倍数、质因数分解
2013-08-18 11:20:43 素数、最大公约数、最下公倍数、质因数分解都是与素数相关的,解决了素数的问题,其他的都可以此为基础求解。 小结: 求1到n之间的素数的基本方法是通过遍历2到sqrt(n),判断每个数是否是素数来得到,…

Spring注解 开发
转载于:https://www.cnblogs.com/JBLi/p/10489541.html

读书:个人成长 -- 即兴演讲
与人交流时,有人发言语无伦次,舌头像打了结。 有人一开讲便滔滔不绝,却毫无重点。 也有人说话索然无味,没法让你投以关注。 如何在任何场合游刃有余地表达? 如何掌控此时此刻,用说话影响他人? …

php mysql环境搭配_centos6.7下搭配apache php mysql环境
安装过程安装apacheapache默认端口为80, 而nginx默认端口也是80, 所以安装apache前, 检查是否安装了nginx, 确保80端口没有被占用, 然后执行以下命令安装apacheyum install httpd httpd-devel启动apache服务/etc/init.d/httpd start或service httpd start停止apache服务/etc/in…

我们如此努力,也不过是个普通人
http://www.nowamagic.net/librarys/eight/posts/2500文 / 張君雅 南方日报曾刊登了一条新闻,大意是说有个女孩子以她的成绩考入北大清华没问题。但她从小参加各种社会活动,深受曾留学法国的母亲“生命的意义在于体验最多而不是最好”影响,决…

Citrix XenServer@cloudstack基本功能测试报告2
Cloudstack功能测试1、创建Zone、Pod、Clusters,添加hosts、Primary Storage、Secondary Storage步骤:1、 登录cloudstack控制板2、 选择基础架构,选择区域,点击查看全部,然后点击添加区域3、 选择基本区域类型4、 输入…

ABP中的Filter(下)
接着上面的一个部分来叙述,这一篇我们来重点看ABP中的AbpUowActionFilter、AbpExceptionFilter、AbpResultFilter这三个部分也是按照之前的思路来一个个介绍,当然这里面如果和前面的Interceptor有重复的部分,那么将会对两者进行一个对比并作出…

LRU算法 -- 链表 完整实现
LRU算法(Least Recently Used) 算是我们经常遇到的一种淘汰算法,其中内存管理模块进行内存页回收时有用到,针对不经常使用的内存页,LRU淘汰策略能够将该内存页回收给操作系统。 属于 我们操作系统设计中的 时间局部性原理,最长时…

python getostime_python中sys,os,time模块的使用(包括时间格式的各种转换)
sys模块sys.argv: 实现从程序外部向程序传递参数。位置参数argv[0]代表py文件本身,运行方法 python xx.py 参数1,参数2 。。self sys.argv[0]name sys.argv[1]age sys.argv[2]print self, name, agesys.getdefaultencoding(): 获取系统当前编码&#…

关于SpringMVC和Struts2的区别
1. 与struts2不同 1、 springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过虑器。 2、 springmvc是基于方法开发,传递参数是通过方法形参,可以设计为单例或多例(建议单例),struts2是基于类开发,…

DC-RC加固修补型砂浆
DC-RC加固修补型砂浆www.hrbjg.net一、DC-RC加固修补型砂浆的产品特点:1、耐火、耐高温、耐腐蚀、耐老化性能优良。2、强度高,抹灰操作性好。3、与原混凝土结构的粘结性能良好。4、无收缩,基本不会产生裂缝。5、二氧化碳、氯化物等透过性差&a…

类,实例,属性习题
class Restaurant(): def __init__(self,restaurant_name,cuisine_type): self.restaurant_namerestaurant_name self.cuisine_typecuisine_type def describle_restaurant(self): print("打印的第一条消息") print("打印的第…

数据结构和算法 -- 学习导图
数据结构和算法 是作为程序员写出高效代码的基础,为了今后的两年在高效代码之路上持续精进,将按照此学习导图进行 算法和数据结构的刻意练习,同时也希望为同样有高效代码追求的伙伴们提供一条学习路径,共同进步。 以下为今后持续…

HDU 1248 寒冰王座(全然背包:入门题)
HDU 1248 寒冰王座(全然背包:入门题) http://acm.hdu.edu.cn/showproblem.php?pid1248 题意: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,仅仅有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前. 死亡骑士:"我要买…

java 彩票系统_JAVA版彩票随机生成系统
import java.io.*;import java.util.Random;class num{public static void main(String[]args){//声明一个随机数组int sjsh[]new int[7];int sum;try{InputStreamReader anew InputStreamReader(System.in);BufferedReader bnew BufferedReader(a);System.out.println ("…

Windows Server 2012 文件服务器群集
概述:之前已经测试了Windows Server 2012系统群集、Hyper-V群集,接下来将测试Windows Server 2012 文件服务器群集功能。实验环境:4台服务器都为Windows Server 2012 DataCenter操作系统在之前配置了群集的基础上,SRV2012服务器新…

023 判断出栈顺序是否正确
1.题目 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。 假设压入栈的所有数字均不相等。例如序列1、2、3、4、5是某栈的压栈序列,序列4、5、3、2、1是该压栈序列对应的一个弹出序列,但4、3…

栈 -- 顺序栈、链式栈的实现 及其应用(函数栈,表达式求值,括号匹配)
文章目录实现顺序栈实现链式栈实现应用函数栈 的应用表达式求值中 的应用括号匹配中 的应用我们使用浏览器的时候经常会用到前进、后退功能。依次访问完一串页面 a – b – c之后点击后退功能,则能够依次看到c – b – a的页面。但是这个过程中,如果后退…

OC中的NSArray和NSMutableArray、NSDictionary和NSMutableDictionary用法
一:NSArray 和NSMutableArray1: NSArray:不可变数组NSArray是OC中使用的数组,只能用来存放OC对象,不能存放非OC对象如基本数据类型它使不可变的,一旦初始化完毕,内容不能改变,也不能添加元素。而…

java中ContentArea_java中TextArea怎么加载指定路径的文本内容
展开全部这设计到IO操作,很62616964757a686964616fe58685e5aeb931333332643334久以前练手写的加载文本到文本域的界面。具体代码第一步:得到一个File对象,需要参数文本路径File file new File("C:\\test.txt");第二步:…

文本分类技术基础
分类体系 分类:给定一个对象,从一个事先定义好的分类体系中挑出一个或多个最适合该对象的类别。 文本分类(TC, Text Categorization):在给定的分类体系下,根据文本内容自动的确定文本关联的类别。从数学角度看,文本分类…

C# 返回值为 listT
public List<T> test<T>(List<T> EntityList) where T : class{return EntityList;} 转载于:https://www.cnblogs.com/enych/p/10497312.html

ceph bluestore 源码分析:ceph-osd内存查看方式及控制源码分析
文章目录内存查看内存控制内存控制源码分析通过gperftools接口获取osd进程实际内存 动态设置cache大小动态调整cache比例trim释放内存本文通过对ceph-osd内存查看跟踪的5种手段以及osd内存控制的方式进行源码层面的说明,并未通过修改相关源码进行控制(水…