/************************************************************************
设计模式
原型模式
所谓原型模式,也就是从一个对象再创建另外一个可定制的对象,而且不需要知道
任何创建的细节。注意的是:必须是同一个类的对象。
从语法角度讲,使用C++来实现原型模式,关键的是【拷贝构造函数】。
在main函数中,有两种写法,第一种是有点问题的:没有使用抽象基类来操作,
第二种是修正了的,使用了抽象基类来操作。
************************************************************************/
【天才】类,抽象基类 ,Clone克隆接口,留给子类实现
//【天才】类
class CGenius
{
public:
CGenius(string strName, int age);
CGenius();
virtual ~CGenius();
virtual void Set(string strName, int age) ;
virtual CGenius* Clone() = 0;
virtual void Show() const;
protected:
string m_strName;
int m_nAge;
};
CGenius::CGenius(string strName, int age) : m_strName(strName), m_nAge(age){}
CGenius::CGenius(){}
CGenius::~CGenius(){}
void CGenius::Set(string strName, int age)
{
this->m_strName = strName;
this->m_nAge = age;
}
void CGenius::Show() const
{
cout << "name is "<<m_strName<<", age is "<<m_nAge<<endl;
}
【爱因斯坦】类,实现了Clone接口,关键用到了拷贝构造函数,需要注意:在写代码过程报了一个错:那就是当为【爱因斯坦】类写了拷贝构造函数时,必须为其父类【天才】类写一个默认的构造函数,否则报错。
//【爱因斯坦】类
class Einstein : public CGenius
{
public:
Einstein(string strName, int age);
Einstein(const Einstein& einstein); //拷贝构造函数
virtual ~Einstein();
virtual void Set(string strName, int age);
virtual CGenius* Clone();
virtual void Show() const;
};
Einstein::Einstein(string strName, int age) : CGenius(strName, age){}
Einstein::Einstein(const Einstein& einstein)
{
this->m_strName = einstein.m_strName;
this->m_nAge = einstein.m_nAge;
}
Einstein::~Einstein(){}
//调用基类函数
void Einstein::Set(string strName, int age)
{
CGenius::Set(strName, age);
}
CGenius* Einstein::Clone()
{
//调用其拷贝构造函数
return new Einstein(*this);
}
//调用基类函数
void Einstein::Show() const
{
CGenius::Show();
}
main函数,在客户端中使用这个模式时,犯了点小二,不过改正了,详见代码和代码注释
int _tmain(int argc, _TCHAR* argv[])
{
//////////////////开始 有点瑕疵的代码///////////////////////////////////////
//期望输出 Einstein, 50
Einstein *pEinstein = new Einstein("Einstein", 50);
pEinstein->Show();
cout<<endl<<"--------------------------------"<<endl;
//下面这行代码就是有瑕疵的地方,这段代码正常运行
//但是却使用了一个dynamic_case转换
//如果把用到的Einstein类名都改为抽象基类CGenius
//完全可以不实用dynamic_case
//详见下面另一段代码
//从pEinstein克隆而来,期望的输出是Einstein, 50
Einstein *pEinstein2 = dynamic_cast<Einstein*>(pEinstein->Clone());
pEinstein2->Show();
cout<<endl<<"--------------------------------"<<endl;
//重新设置一下pEinstein2的值,期望输出zhangsan, 51
pEinstein2->Set("zhangsan", 51);
pEinstein2->Show();
cout<<endl<<"--------------------------------"<<endl;
//重新输入pEinstein的值,期望输出Einstein, 50
pEinstein->Show();
delete pEinstein; pEinstein = NULL;
delete pEinstein2; pEinstein2 = NULL;
//////////////////结束 有点瑕疵的代码///////////////////////////////////////
//使用抽象基类指针,多态来使用原型模式
cout<<endl<<"--------------------------------"<<endl;
cout<<endl<<"----------华丽的分割线----------------------"<<endl;
cout<<endl<<"--------------------------------"<<endl;
//////////////////开始 修正后的代码///////////////////////////////////////
//期望输出 爱因斯坦, 50
CGenius* pGenius = new Einstein("爱因斯坦", 50);
pGenius->Show();
cout<<endl<<"--------------------------------"<<endl;
//从pGenius克隆而来,期望输出 爱因斯坦, 50
CGenius* pGenius2 = pGenius->Clone();
pGenius2->Show();
cout<<endl<<"--------------------------------"<<endl;
//改变pGenius2的值,期望输出 张三,51
pGenius2->Set("张三", 51);
pGenius2->Show();
cout<<endl<<"--------------------------------"<<endl;
//重新输出pGenius的值,期望输出 爱因斯坦, 50
pGenius->Show();
delete pGenius; pGenius = NULL;
delete pGenius2; pGenius2 = NULL;
//////////////////结束 修正后的代码///////////////////////////////////////
cout<<endl<<endl;
return 0;
}
运行情况如下