【有毒的设计模式】原型模式
来源:互联网 发布:在国外可以用淘宝吗 编辑:程序博客网 时间:2024/04/29 07:05
//说些废话
。。这个模式毒死我了,真的毒死我了,毒了我8个小时,终于释怀了。。。特么一开始看这个模式,我想来想去,这尼玛不就直接调用个复制构造函数的事情吗。然后
while(1)
{
看来看去->查查资料->看看别人的blog->理解一下;
}
直接死循环了,8小时后的现在,终于break了,WTF,很晚了,不写那么多,简单说说重点贴个代码跑路。。
//部分资料来源
1.C++设计模式:http://www.jellythink.com/archives/105
2.程杰——大话设计模式
//适用场合(来源部分资料1)
1.当我们的对象类型不是开始就能确定的,而这个类型是在运行期确定的话,那么我们通过这个类型的对象克隆出一个新的对象比较容易一些;
2.有的时候,我们需要一个对象在某个状态下的副本,此时,我们使用原型模式是最好的选择;例如:一个对象,经过一段处理之后,其内部的状态发生了变化;这个时候,我们需要一个这个状态的副本,如果直接new一个新的对象的话,但是它的状态是不对的,此时,可以使用原型模式,将原来的对象拷贝一个出来,这个对象就和之前的对象是完全一致的了;
3.当我们处理一些比较简单的对象时,并且对象之间的区别很小,可能就几个属性不同而已,那么就可以使用原型模式来完成,省去了创建对象时的麻烦了;
4.有的时候,创建对象时,构造函数的参数很多,而自己又不完全的知道每个参数的意义,就可以使用原型模式来创建一个新的对象,不必去理会创建的过程,让创建过程见鬼去吧。
//正文
上个代码再说话。。
#include <QCoreApplication>#include <iostream>#include <string>#include <iomanip>using namespace std;class Work{public: Work(string a_string):name(a_string){} Work(const Work& str); Work& operator=(const Work &str) { if(this != &str) { Work strTemp(str); string pTemp = strTemp.name; strTemp.name = name; name = pTemp; } return *this; } string name;};class Prototype{public: Prototype(){} virtual ~Prototype(){} virtual Prototype* Clone() = 0;};class ConcretePrototype : public Prototype{public: ConcretePrototype(Work *rhs_mywork,int num):mywork(rhs_mywork),mynum(num){} virtual ~ConcretePrototype(){} ConcretePrototype(const ConcretePrototype& rhs) { mywork = new Work(rhs.mywork->name); //mywork = rhs.mywork; mynum = rhs.mynum; } /*-------------------set---------------------*/ void setWord(string a_string) { mywork->name = a_string; } /*--------------------------------------------*/ /*------------------putout--------------------*/ void putout() { cout<<"mywork->name:"<<'\t'<<mywork->name<<endl; cout<<"&mywork:"<<"\t"<<&mywork<<endl; cout<<"&mywork->name"<<"\t"<<&mywork->name<<endl; cout<<"mynum:"<<"\t\t"<<mynum<<endl; cout<<"&mynum:"<<"\t\t"<<&mynum<<endl; cout<<endl; } /*---------------------------------------------*/ /*-------------------clone---------------------*/ virtual ConcretePrototype* Clone() { return new ConcretePrototype(*this); } /*---------------------------------------------*/private: Work *mywork; int mynum;};int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); string mystring = "wocao"; string mystring2 = "wocao2"; Work *mywork = new Work(mystring); ConcretePrototype* conProA = new ConcretePrototype(mywork,10); ConcretePrototype* conProB = conProA->Clone(); cout<<"A before setWord:"<<endl; conProA->putout(); cout<<"B before setWord:"<<endl; conProB->putout(); conProA->setWord(mystring2); cout<<"A after setWord:"<<endl; conProA->putout(); cout<<"B after setWord:"<<endl; conProB->putout(); return a.exec();}
毒死了。。这段代码其实有缺陷的,不过我不想改了,越改越难理解。。。
其实你可以看得出,Work类应该用一个Clone方法的,不然那里就没有用原型模式了,不过我注重说的是Prototype和他的子类,所以那个我就不管了。
其实原型模式,就做了一件事情,调用复制构造函数。 哦哦哦?就这样?
对,就这样。。只是要实现一下复制构造函数,不能用默认的,不然只能浅拷贝,下面详讲
原型模式(Protorype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。[DP]
=================================浅拷贝和深拷贝========================================
其实原型模式注意的地方有一个,很重要,就是复制构造函数的浅拷贝和深拷贝。
我们知道默认构造函数是浅拷贝的。
浅拷贝,对于值类型(包括string),则对该字段逐位复制,就如同我的子类里面int mynum一样,复制构造的时候,直接 = 赋值,他们的地址就不同了。
对于引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用统一对象。(意思就是不会new一个新对象,他们地址还是一样)
深拷贝,把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象,就如同我new Work一样。(默认复制构造函数 和 原型模式的复制构造函数 区别就在这)
=====================================================================================
理解完之后,clone就好简单了,直接return+调用一次复制构造函数。
//还有个事情说一下,我那个重载=操作符没有用上,只是记一下这种考虑了异常安全的对象间赋值操作。
//问题
1.
Q:原型模式有什么好处?
A:原型模式,从一个对象再创建另外一个可以定制的对象,而且不需要知道任何创建的细节。
一般在初始化信息不发生变化的情况下,隐藏对象创建细节,创建对象。
//坏处
说说坏处吧,你每一个子类都要写一个clone方法。这其实有点不切合实际的。
2.
Q:什么时候用原型模式?
A:最简单直接一句话概括,你要new一个跟现有对象一样的对象,或者只是很小部分属性有点不同。这就用咯。可以set来改那部分属性。
再提一下吧最后,原型模式其实就是: 用clone调用复制构造函数+重写复制构造函数(有类对象成员就深拷贝,只是值类型成员直接浅拷贝或者用默认)
- 【有毒的设计模式】原型模式
- 【有毒的设计模式】简单工厂模式
- 【有毒的设计模式】策略模式
- 【有毒的设计模式】装饰模式
- 【有毒的设计模式】代理模式
- 【有毒的设计模式】工厂方法模式
- 【有毒的设计模式】模板方法模式
- 【有毒的设计模式】外观模式
- 【有毒的设计模式】建造者模式
- 【有毒的设计模式】迪米特法则
- 设计模式:原型模式
- 设计模式------原型模式
- 设计模式 原型模式
- 设计模式-【原型模式】
- 设计模式-原型模式
- 设计模式-原型模式
- 设计模式-原型模式
- 设计模式-原型模式
- Android开发实践:使用Service还是Thread
- android 开发的1/365
- NSCopying、NSCoding
- JavaScript编码解码
- 12.Java IO: OutputStream--输出流
- 【有毒的设计模式】原型模式
- 深入掌握JMS(七):DeliveryMode例子
- 刷题_day1_vv
- 有序链表合并
- 《NumPy Beginner's Guide》笔记Chapter6
- UVa 378 - Intersecting Lines
- 把字符串中空格替换为"%20"
- iOS解决NSUserDefaults存储失败问题
- 《NumPy Beginner's Guide》笔记Chapter7