C++设计模式 之 原型模式
2015-07-21 11:51
405 查看
意图:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性:
当一个系统应该独立于他的产品创建、构成和表示时,需要使用原型模式
当要实例化的类是在运行时刻指定时,如通过动态装载
为了避免创建一个与产品类层次平行的工厂类层次时
当一个类的实例只能有几个不同状态组合中的一种时,建立相应数目的原型并克隆他们可能比每次用合适的状态手工实例化该类更方便一些。
prototype.h
[cpp] view
plaincopy
//设计模式之原型模式
/*
解析:
Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性,
但是通过不同派生类实现的Clone接口函数可以完成与"虚拟构造函数"同样的效果.举一个例子来
解释这个模式的作用,假设有一家店铺是配钥匙的,他对外提供配制钥匙的服务(提供Clone接口函
数),你需要配什么钥匙它不知道只是提供这种服务,具体需要配什么钥匙只有到了真正看到钥匙
的原型才能配好.也就是说,需要一个提供这个服务的对象,同时还需要一个原型(Prototype),不
然不知道该配什么样的钥匙.
*/
//声明一个虚拟基类,所有的原型都从这个基类继承,
class prototype
{
public:
prototype(){}
virtual ~prototype(){}
virtual prototype* clone() = 0;//纯虚函数,需要供继承者自行实现
};
// 派生自Prototype,实现Clone方法
class concreateprototype1:public prototype
{
public:
concreateprototype1();
concreateprototype1(const concreateprototype1&);
virtual ~concreateprototype1();
virtual prototype* clone();
};
// 派生自Prototype,实现Clone方法
class concreateprototype2:public prototype
{
public:
concreateprototype2();
concreateprototype2(const concreateprototype2&);
virtual ~concreateprototype2();
virtual prototype* clone();
};
prototype.cpp
[cpp] view
plaincopy
#include "prototype.h"
#include <iostream>
using namespace std;
concreateprototype1::concreateprototype1()
{
cout<<"concreteprototype1 create"<<endl;
}
concreateprototype1::concreateprototype1(const concreateprototype1 &contype )
{
cout<<"copy the concreteprototype1"<<endl;
}
concreateprototype1::~concreateprototype1()
{
cout<<"destruction of concreteprototype1"<<endl;
}
prototype* concreateprototype1::clone()
{
return new concreateprototype1(*this);
}
concreateprototype2::concreateprototype2()
{
cout<<"concreteprototype2 create"<<endl;
}
concreateprototype2::concreateprototype2(const concreateprototype2 &contype )
{
cout<<"copy the concreteprototype2"<<endl;
}
concreateprototype2::~concreateprototype2()
{
cout<<"destruction of concreteprototype2"<<endl;
}
prototype* concreateprototype2::clone()
{
return new concreateprototype2(*this);
}
使用的时候可以这么使用:
[cpp] view
plaincopy
prototype *ptype1 = new concreateprototype1();
prototype *copytype1 = ptype1->clone();
delete ptype1;
delete copytype1;
这种情况是浅复制,被复制的对象的所有变量都含有原来的对象相同的值,而所有的对其他对象的引用的仍指向原来的对象。
所以,如果我们想修改任意一个引用指向的的对象,那么所有对象的这个引用这项对象都会进行修改:
比如,三个简历复制过来名字都是 XXX,而如果我们修改任意一个简历的名字为YYY,则三个简历名字都是YYY了,即浅复制。
所以,我们就更需要这样的一种需求,把要复制的对象所有引用的对象都复制一遍。这样复制出来的对象都是不同的,独立的,这种复制
方式为“深复制”!深复制会把引用对象的变量指向复制过的新对象,而不是原来的被引用的对象!
但是深复制到底要复制多少层,需要事先考虑好!而且当心出现循环引用的问题!
代码:
resume.h
[cpp] view
plaincopy
//首先抽象一个基类
class resume
{
protected:
char *name;
public:
resume()
{
}
virtual ~resume()
{
}
virtual void set(const char *str)
{
}
virtual void show()
{
}
virtual resume* clone()
{
return 0;
}
};
class ResumeA : public resume
{
public:
ResumeA(const char *str); //构造函数
ResumeA(const ResumeA &r); //拷贝构造函数
~ResumeA(); //析构函数
ResumeA* clone(); //克隆,关键所在
void show(); //显示内容
};
class ResumeB : public resume
{
public:
ResumeB(const char *str); //构造函数
ResumeB(const ResumeB &r); //拷贝构造函数
~ResumeB(); //析构函数
ResumeB* clone(); //克隆,关键所在
void show(); //显示内容
};
resume.cpp
[cpp] view
plaincopy
#include "resume.h"
#include <iostream>
using namespace std;
ResumeA::ResumeA(const char *str)
{
if(str == NULL) {
name = new char[1];
name[0] = '\0';
}
else {
name = new char[strlen(str)+1];
strcpy(name, str);
}
}
ResumeA::~ResumeA() { delete [] name;}
ResumeA::ResumeA(const ResumeA &r) {
name = new char[strlen(r.name)+1];
strcpy(name, r.name);
}
ResumeA* ResumeA::clone() {
return new ResumeA(*this);
}
void ResumeA::show() {
cout<<"ResumeA name : "<<name<<endl;
}
ResumeB::ResumeB(const char *str)
{
if(str == NULL) {
name = new char[1];
name[0] = '\0';
}
else {
name = new char[strlen(str)+1];
strcpy(name, str);
}
}
ResumeB::~ResumeB() { delete [] name;}
ResumeB::ResumeB(const ResumeB &r) {
name = new char[strlen(r.name)+1];
strcpy(name, r.name);
}
ResumeB* ResumeB::clone() {
return new ResumeB(*this);
}
void ResumeB::show() {
cout<<"ResumeB name : "<<name<<endl;
}
int main()
{
resume *r1 = new ResumeA("A");
resume *r2 = new ResumeB("B");
resume *r3 = r1->clone();
resume *r4 = r2->clone();
r1->show();
r2->show();
//删除r1,r2
delete r1;
delete r2;
r1 = r2 = NULL;
//深拷贝所以对r3,r4无影响
r3->show();
r4->show();
delete r3; delete r4;
r3 = r4 = NULL;
}
上述代码中:ResumeA,ResumeB中的构造函数是只是按照形参重新构建一个新的对象,而clone()会New一个新的对象,所以删除掉r1,r2不会对r3,r4有任何影响!
其实这个设计模式比较简单,我们总结一下具体操作步骤。
1、声明一个抽象基类,并定义clone()函数为纯虚函数。
2、实例化各个子类,并且实现复制构造函数,并实现clone()函数
3、继承抽象基类,如果自己的类中并没有重载构造函数,则为浅复制,重载后在clone()里return New的对象则为深复制,主要还是将引用对象的变量指向新的对象!
好了,估计这篇文章也就我自己能看的懂。哈哈!
友情提示,参考文章:http://blog.csdn.net/lbqbraveheart/article/details/7086883
参考书籍:大话设计模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性:
当一个系统应该独立于他的产品创建、构成和表示时,需要使用原型模式
当要实例化的类是在运行时刻指定时,如通过动态装载
为了避免创建一个与产品类层次平行的工厂类层次时
当一个类的实例只能有几个不同状态组合中的一种时,建立相应数目的原型并克隆他们可能比每次用合适的状态手工实例化该类更方便一些。
prototype.h
[cpp] view
plaincopy
//设计模式之原型模式
/*
解析:
Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性,
但是通过不同派生类实现的Clone接口函数可以完成与"虚拟构造函数"同样的效果.举一个例子来
解释这个模式的作用,假设有一家店铺是配钥匙的,他对外提供配制钥匙的服务(提供Clone接口函
数),你需要配什么钥匙它不知道只是提供这种服务,具体需要配什么钥匙只有到了真正看到钥匙
的原型才能配好.也就是说,需要一个提供这个服务的对象,同时还需要一个原型(Prototype),不
然不知道该配什么样的钥匙.
*/
//声明一个虚拟基类,所有的原型都从这个基类继承,
class prototype
{
public:
prototype(){}
virtual ~prototype(){}
virtual prototype* clone() = 0;//纯虚函数,需要供继承者自行实现
};
// 派生自Prototype,实现Clone方法
class concreateprototype1:public prototype
{
public:
concreateprototype1();
concreateprototype1(const concreateprototype1&);
virtual ~concreateprototype1();
virtual prototype* clone();
};
// 派生自Prototype,实现Clone方法
class concreateprototype2:public prototype
{
public:
concreateprototype2();
concreateprototype2(const concreateprototype2&);
virtual ~concreateprototype2();
virtual prototype* clone();
};
prototype.cpp
[cpp] view
plaincopy
#include "prototype.h"
#include <iostream>
using namespace std;
concreateprototype1::concreateprototype1()
{
cout<<"concreteprototype1 create"<<endl;
}
concreateprototype1::concreateprototype1(const concreateprototype1 &contype )
{
cout<<"copy the concreteprototype1"<<endl;
}
concreateprototype1::~concreateprototype1()
{
cout<<"destruction of concreteprototype1"<<endl;
}
prototype* concreateprototype1::clone()
{
return new concreateprototype1(*this);
}
concreateprototype2::concreateprototype2()
{
cout<<"concreteprototype2 create"<<endl;
}
concreateprototype2::concreateprototype2(const concreateprototype2 &contype )
{
cout<<"copy the concreteprototype2"<<endl;
}
concreateprototype2::~concreateprototype2()
{
cout<<"destruction of concreteprototype2"<<endl;
}
prototype* concreateprototype2::clone()
{
return new concreateprototype2(*this);
}
使用的时候可以这么使用:
[cpp] view
plaincopy
prototype *ptype1 = new concreateprototype1();
prototype *copytype1 = ptype1->clone();
delete ptype1;
delete copytype1;
这种情况是浅复制,被复制的对象的所有变量都含有原来的对象相同的值,而所有的对其他对象的引用的仍指向原来的对象。
所以,如果我们想修改任意一个引用指向的的对象,那么所有对象的这个引用这项对象都会进行修改:
比如,三个简历复制过来名字都是 XXX,而如果我们修改任意一个简历的名字为YYY,则三个简历名字都是YYY了,即浅复制。
所以,我们就更需要这样的一种需求,把要复制的对象所有引用的对象都复制一遍。这样复制出来的对象都是不同的,独立的,这种复制
方式为“深复制”!深复制会把引用对象的变量指向复制过的新对象,而不是原来的被引用的对象!
但是深复制到底要复制多少层,需要事先考虑好!而且当心出现循环引用的问题!
代码:
resume.h
[cpp] view
plaincopy
//首先抽象一个基类
class resume
{
protected:
char *name;
public:
resume()
{
}
virtual ~resume()
{
}
virtual void set(const char *str)
{
}
virtual void show()
{
}
virtual resume* clone()
{
return 0;
}
};
class ResumeA : public resume
{
public:
ResumeA(const char *str); //构造函数
ResumeA(const ResumeA &r); //拷贝构造函数
~ResumeA(); //析构函数
ResumeA* clone(); //克隆,关键所在
void show(); //显示内容
};
class ResumeB : public resume
{
public:
ResumeB(const char *str); //构造函数
ResumeB(const ResumeB &r); //拷贝构造函数
~ResumeB(); //析构函数
ResumeB* clone(); //克隆,关键所在
void show(); //显示内容
};
resume.cpp
[cpp] view
plaincopy
#include "resume.h"
#include <iostream>
using namespace std;
ResumeA::ResumeA(const char *str)
{
if(str == NULL) {
name = new char[1];
name[0] = '\0';
}
else {
name = new char[strlen(str)+1];
strcpy(name, str);
}
}
ResumeA::~ResumeA() { delete [] name;}
ResumeA::ResumeA(const ResumeA &r) {
name = new char[strlen(r.name)+1];
strcpy(name, r.name);
}
ResumeA* ResumeA::clone() {
return new ResumeA(*this);
}
void ResumeA::show() {
cout<<"ResumeA name : "<<name<<endl;
}
ResumeB::ResumeB(const char *str)
{
if(str == NULL) {
name = new char[1];
name[0] = '\0';
}
else {
name = new char[strlen(str)+1];
strcpy(name, str);
}
}
ResumeB::~ResumeB() { delete [] name;}
ResumeB::ResumeB(const ResumeB &r) {
name = new char[strlen(r.name)+1];
strcpy(name, r.name);
}
ResumeB* ResumeB::clone() {
return new ResumeB(*this);
}
void ResumeB::show() {
cout<<"ResumeB name : "<<name<<endl;
}
int main()
{
resume *r1 = new ResumeA("A");
resume *r2 = new ResumeB("B");
resume *r3 = r1->clone();
resume *r4 = r2->clone();
r1->show();
r2->show();
//删除r1,r2
delete r1;
delete r2;
r1 = r2 = NULL;
//深拷贝所以对r3,r4无影响
r3->show();
r4->show();
delete r3; delete r4;
r3 = r4 = NULL;
}
上述代码中:ResumeA,ResumeB中的构造函数是只是按照形参重新构建一个新的对象,而clone()会New一个新的对象,所以删除掉r1,r2不会对r3,r4有任何影响!
其实这个设计模式比较简单,我们总结一下具体操作步骤。
1、声明一个抽象基类,并定义clone()函数为纯虚函数。
2、实例化各个子类,并且实现复制构造函数,并实现clone()函数
3、继承抽象基类,如果自己的类中并没有重载构造函数,则为浅复制,重载后在clone()里return New的对象则为深复制,主要还是将引用对象的变量指向新的对象!
好了,估计这篇文章也就我自己能看的懂。哈哈!
友情提示,参考文章:http://blog.csdn.net/lbqbraveheart/article/details/7086883
参考书籍:大话设计模式
相关文章推荐
- PropertyChangeListener简单理解
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 设计模式之创建型模式
- 浅谈设计模式的学习
- PHP设计模式之装饰者模式代码实例
- php设计模式之单例模式实例分析
- 介绍php设计模式中的工厂模式
- PHP设计模式之适配器模式代码实例
- 浅谈c#设计模式之单一原则
- C#设计模式之观察者模式实例讲解
- C#设计模式之单例模式实例讲解
- 深入理解JavaScript系列(28):设计模式之工厂模式详解
- 面向对象设计模式的核心法则
- JavaScript设计模式之单件模式介绍
- 深入理解JavaScript系列(25):设计模式之单例模式详解
- JavaScript设计模式之外观模式实例
- 常见的PHP五种设计模式小结
- 小议javascript 设计模式 推荐
- javascript 设计模式之单体模式 面向对象学习基础