上篇文章,介紹了《大話設計模式》的第8章——工廠方法。
本篇,來介紹《大話設計模式》的第9章——原型模式。并通過C++代碼實現(xiàn)實例代碼的功能。
1 原型模式
原型模式(Prototype):用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。
原型模式的類圖如下:
- Client:讓一個原型克隆自身從而創(chuàng)建一個新的對象Prototype:原型類,聲明一個克隆自身的接口ConcreatePrototype:具體原型類,實現(xiàn)一個克隆自身的操作
2 實例
背景:書中小故事,小菜要去找工作,準備了很厚一疊簡歷,大鳥在感慨他那時找工作的時候,都是手寫簡歷,現(xiàn)在印簡歷就像印草紙一樣,由此聯(lián)想到代碼中的復制粘貼。
題目:用代碼的形式來實現(xiàn)簡歷類的功能,要求必須要有姓名,可以設置性別和年齡,可以設置工作經歷,最終需要寫三份簡歷。
2.1 版本一:單一簡歷類
版本一的實現(xiàn)比較簡單,僅設計一個簡歷類。
2.1.1 簡歷類
簡歷類的實現(xiàn)如下:
- 簡歷類構造時傳入姓名作為參數(shù)調用設置個人信息方法SetPersonalInfo,可設置性別和年齡調用設置工作經歷方法SetWorkExperience,可設置工作時間與工作的公司調用顯示方法Display,可顯示簡歷的完整內容
// 簡歷類
class Resume
{
public:
Resume(std::string name)
{
m_name = name;
}
// 設置個人信息
void SetPersonalInfo(std::string sex, int age)
{
m_sex = sex;
m_iAge = age;
}
// 設置工作經歷
void SetWorkExperience(std::string timeArea, std::string company)
{
m_timeArea = timeArea;
m_company = company;
}
// 顯示
void Display()
{
printf("%s %s %dn", m_name.c_str(), m_sex.c_str(), m_iAge);
printf("工作經歷:%s %sn", m_timeArea.c_str(), m_company.c_str());
}
private:
std::string m_name;
std::string m_sex;
int m_iAge;
std::string m_timeArea;
std::string m_company;
};
2.1.2 主函數(shù)
首先,實例化三份簡歷,并分別設置具體的內容,
然后,就可以調用展示接口來顯示出來了。
int main()
{
// 實例化三份簡歷
Resume a = Resume("大鳥");
a.SetPersonalInfo("男", 29);
a.SetWorkExperience("2018-2020", "XX公司");
Resume b = Resume("大鳥");
b.SetPersonalInfo("男", 29);
b.SetWorkExperience("2018-2020", "XX公司");
Resume c = Resume("大鳥");
c.SetPersonalInfo("男", 29);
c.SetWorkExperience("2018-2020", "XX公司");
// 顯示出來
a.Display();
b.Display();
c.Display();
return 0;
}
代碼運行效果如下:
下面來看版本二。
2.2 版本二:原型模式
版本二,使用原型模型,設計了一個簡歷原型類,定義了簡歷所具有的基本信息及接口,簡歷類則繼承簡歷原型類,
另外,工作經歷設計為一個單獨類,通過組合方式,作為簡歷類的一部分。
注1:書中代碼使用的C#,C#中有MemberwiseClone方法進行拷貝,而C++中無此方法,因此需要重新實現(xiàn)一個Clone方法。
注2:對對象進行拷貝時,會涉及到淺拷貝與深拷貝的概念,而MemberwiseClone方法對于引用類型的對象,復制的是引用而不是復制對象,這樣就會帶來修改了復制后的對象,原對象也會被修改。因此,書中例子講工作經歷單獨拎出來作為一個類,拷貝簡歷時,簡歷中的工作經歷將為引用類型,以此來對比演示淺拷貝帶來的影響。解決方法就是改為深拷貝,在工作經歷類的內部也實現(xiàn)一個Clone方法。
2.2.1 工作經歷類、簡歷原型類與簡歷類
這里需要實現(xiàn)三個類:
- 工作經歷類:作為簡歷的一部分,實現(xiàn)工作時間與對應的工作公司的信息,并提供克隆接口簡歷原型類:一個抽象類,定義了簡歷所具有的基本信息及接口,并提供克隆接口,實現(xiàn)簡歷克隆簡歷類:繼承簡歷原型類,并實現(xiàn)簡歷原型中定義的方法
// 工作經歷
class WorkExperience
{
public:
WorkExperience() {}
~WorkExperience(){}
WorkExperience(WorkExperience *work)
{
this->m_timeArea = work->m_timeArea;
this->m_company = work->m_company;
}
// 設置/獲取工作時間
void SetWorkTiemArea(std::string timeArea)
{
m_timeArea = timeArea;
}
std::string GetWorkTiemArea()
{
return m_timeArea;
}
// 設置/獲取工作公司
void SetWorkCompany(std::string company)
{
m_company = company;
}
std::string GetWorkCompany()
{
return m_company;
}
// Clone
WorkExperience *Clone()
{
return new WorkExperience(this);
}
private:
std::string m_timeArea;
std::string m_company;
};
// 簡歷原型類
class Prototype
{
public:
virtual void SetPersonalInfo(std::string sex, int age) = 0;
virtual void Display() = 0;
virtual Prototype *Clone() = 0;
protected:
std::string m_name;
std::string m_sex;
int m_iAge;
std::string m_timeArea;
std::string m_company;
};
// 簡歷類
class Resume : public Prototype
{
public:
Resume(std::string name)
{
m_name = name;
m_pWork = new WorkExperience();
}
~Resume()
{
if (m_pWork)
{
delete m_pWork;
}
}
// 設置個人信息
void SetPersonalInfo(std::string sex, int age)
{
m_sex = sex;
m_iAge = age;
}
// 設置工作經歷
void SetWorkExperience(std::string timeArea, std::string company)
{
m_pWork->SetWorkTiemArea(timeArea);
m_pWork->SetWorkCompany(company);
}
// 顯示
void Display()
{
printf("%s %s %dn", m_name.c_str(), m_sex.c_str(), m_iAge);
printf("工作經歷:%s %sn", m_pWork->GetWorkTiemArea().c_str(), m_pWork->GetWorkCompany().c_str());
}
Resume *Clone()
{
Resume *pClone = new Resume(m_name);
pClone->SetPersonalInfo(m_sex, m_iAge);
return pClone;
}
private:
WorkExperience *m_pWork;
};
2.2.2 主函數(shù)
首先,實例化了一個簡歷A,并設置一些基礎信息。
然后,通過克隆的方式,產生簡歷B與簡歷C,并對簡歷B與簡歷C進行個性化修改。
最后,調用顯示接口顯示簡歷的內容。
int main()
{
// 實例化三份簡歷
Resume a = Resume("大鳥");
a.SetPersonalInfo("男", 29);
a.SetWorkExperience("2018-2020", "XX公司");
Resume *b = a.Clone();
b->SetWorkExperience("2018-2021", "YY公司");
Resume *c = a.Clone();
c->SetPersonalInfo("男", 24);
c->SetWorkExperience("2018-2022", "ZZ公司");
// 顯示出來
a.Display();
b->Display();
c->Display();
delete b;
delete c;
return 0;
}
代碼運行效果如下:
原型模式的主要特點在于設計了一個克隆方法,通過克隆,將當前對象的當前狀態(tài)做一個拷貝,形成一個新的對象,注意體會這里的“當前狀態(tài)”,它不是初始狀態(tài),而是在程序運行到某一時刻時其內部屬性的最新狀態(tài)。
總結
本篇介紹了設計模式中的原型模式,并通過簡歷編寫的實例,使用C++編程,來演示原型模式的使用。
文章推薦