C++ 裝飾者模式解析

裝飾者模式的概念

裝飾者模式指的是動態的將責任附加到對象上,想要擴展其功能,裝飾者提供有別於繼承的另外一種選擇。(參考《Head First 設計模式》)c++

我的理解:裝飾者就是一種類包類 就是在構造函數裏面,添加類做爲參數。編程

裝飾者模式原則

  • 封裝變化
  • 多用組合,少用繼承
  • 針對接口編程,不針對實質編程
  • 爲交互對象的鬆耦合設計而努力
  • 對擴展開放,對修改關閉

裝飾者模式實例

  • 例如男生和女生能夠被認爲是被裝飾者,洗澡和吃飯能夠理解爲裝飾行爲, 就是裝飾者模式,在我看來最大的好處 就是行爲與行爲者能夠分開,畢竟好擴展。 就是能夠今天是男生洗澡,女生吃飯, 也能夠是女生洗澡 男生吃飯。 接下來來實現這一行爲

首先是基準類的頭文件,男生女生都是人 因此以人做爲基準類的聲明以下,定義了兩個純虛函數,一個是人的類別,一個是人的行爲。設計模式

//全部的基類 人
class People {
public:
	virtual void personType()= 0; //人的類型
	virtual void personAction() = 0; //人的活動
};
複製代碼

接下來是被裝飾者男生女生各自的類的行爲和活動bash

頭文件:函數

//被裝飾者 :男生
class Boy:public People
{
public:
	//繼承人的兩個方法
	void personType();
	void personAction();
};

//被裝飾者:女生
class Girl:public People
{
public:
	void personType();
	void personAction();
};
複製代碼

各自類的實現以下:測試

//實現相關類
//男生類
void Boy::personType()
{
	cout << "Boy:" << endl;
}

void Boy::personAction()
{
	cout << "Boy要作的事情是" << endl;
}

//女生類
void Girl::personType()
{
	cout << "Girl:" << endl;
}

void Girl::personAction()
{
	cout << "Girl要作的事情是" << endl;
}
複製代碼

接下來是定義一個裝飾行爲的基類,也是繼承於人,這個是裝飾者模式必需要作的一個東西。ui

裝飾者基類的聲明spa

//裝飾者行爲基類:繼承於人
class PersonConduct:public People
{
public:
	PersonConduct(People *cur_people);
    
	void personType();
	void personAction();

protected:
	People *m_pPeople;
};
複製代碼

接下來是兩個吃飯和洗澡行爲的聲明設計

//裝飾行爲:吃飯
class Eat:public PersonConduct
{
public:
	Eat(People *cur_people):PersonConduct(cur_people){}
	void personType();
	void personAction();
};

//裝飾行爲:洗澡
class Bash:public PersonConduct
{
public:
	Bash(People *cur_people):PersonConduct(cur_people){}
	void personType();
	void personAction();
};
複製代碼

其中一個主要的點,須要構造函數中添加 基類的指針,以實現可以調用被裝飾者的動做。3d

具體裝飾行爲類實現的代碼以下:

//裝飾行爲基類
PersonConduct::PersonConduct(People *cur_people)
{
	m_pPeople= cur_people;
}
void PersonConduct::personType()
{
	m_pPeople->personType();
}

void PersonConduct::personAction()
{
	m_pPeople->personAction();
}

//裝飾行爲:基類
void Eat::personType()
{
	m_pPeople->personType();
	cout << "肚子很餓" << endl;
	return;
}

void Eat::personAction()
{
	m_pPeople->personAction();
	cout << "正在吃飯" << endl;
}

//裝飾行爲:洗澡類

void Bash::personType()
{
	m_pPeople->personType();
	cout << "身上有味道" << endl;
}

void Bash::personAction()
{
	m_pPeople->personAction();
	cout << "正在洗澡" << endl;
}

複製代碼

測試是否實現裝飾者模式的代碼以下:

People * cur_boy = new Boy();
	People *  cur_girl = new Girl();

	PersonConduct * cur_eat_action = new Eat(cur_girl); //綁定女孩
	cur_eat_action->personType();
	cur_eat_action->personAction();

	PersonConduct * cur_bash_action = new Bash(cur_boy);//綁定男孩
	cur_bash_action->personType();
	cur_bash_action->personAction();
複製代碼

執行結果:

能夠看出,完美的實現了裝飾者行爲,固然,代碼還有不完善的地方 在於沒有釋放內存最後。都要delete 指針。可是但願能夠幫助你們很好的理解裝飾者模式。

裝飾者模式的注意事項

顯然 裝飾者模式的好處顯而易見,就是對象和操做分離,能夠這麼理解。吃飯不是隻有男生能吃,也不是隻有女生能吃,若是使用繼承的話,須要寫男生繼承一次,女生繼承一次,若是有不少行爲的話,顯然代碼量巨大,因此使用裝飾者模式能夠很好的解決這一問題,固然,若是當對象是單一的狀況下,使用裝飾者模式就顯得很麻煩了,由於還要寫裝飾者基類啥的,每一個行爲一個類 很麻煩,但願你們能夠活學活用最好。這也是設計模式的意義所在。

實例完整代碼

頭文件:

#include "stdafx.h"

using namespace std;

//全部的基類 人
class People {
public:
	virtual void personType()= 0; //人的類型
	virtual void personAction() = 0; //人的活動
};

//被裝飾者 :男生
class Boy:public People
{
public:
	//繼承人的兩個方法
	void personType();
	void personAction();
};

//被裝飾者:女生
class Girl:public People
{
public:
	void personType();
	void personAction();
};

//裝飾者行爲基類:繼承於人
class PersonConduct:public People
{
public:
	PersonConduct(People *cur_people);
    
    void personType();
    void personAction();

protected:
	People *m_pPeople;
};

//裝飾行爲:吃飯
class Eat:public PersonConduct
{
public:
	Eat(People *cur_people):PersonConduct(cur_people){}
	void personType();
	void personAction();
};

//裝飾行爲:洗澡
class Bash:public PersonConduct
{
public:
	Bash(People *cur_people):PersonConduct(cur_people){}
	void personType();
	void personAction();
};
複製代碼

實現文件

// DecorationMode.cpp : 定義控制檯應用程序的入口點。
// 裝飾者模式

#include "stdafx.h"
#include "DecorationMode.h"

using namespace std;
//實現相關類
//男生類
void Boy::personType()
{
	cout << "Boy:" << endl;
}

void Boy::personAction()
{
	cout << "Boy要作的事情是" << endl;
}

//女生類
void Girl::personType()
{
	cout << "Girl:" << endl;
}

void Girl::personAction()
{
	cout << "Girl要作的事情是" << endl;
}

//裝飾行爲基類
PersonConduct::PersonConduct(People *cur_people)
{
	m_pPeople= cur_people;
}
void PersonConduct::personType()
{
	m_pPeople->personType();
}

void PersonConduct::personAction()
{
	m_pPeople->personAction();
}

//裝飾行爲:基類
void Eat::personType()
{
	m_pPeople->personType();
	cout << "肚子很餓" << endl;
	return;
}

void Eat::personAction()
{
	m_pPeople->personAction();
	cout << "正在吃飯" << endl;
}

//裝飾行爲:洗澡類

void Bash::personType()
{
	m_pPeople->personType();
	cout << "身上有味道" << endl;
}

void Bash::personAction()
{
	m_pPeople->personAction();
	cout << "正在洗澡" << endl;
}


int _tmain(int argc, _TCHAR* argv[])
{
	People * cur_boy = new Boy();
	People *  cur_girl = new Girl();

	PersonConduct * cur_eat_action = new Eat(cur_girl); //綁定女孩
	cur_eat_action->personType();
	cur_eat_action->personAction();

	PersonConduct * cur_bash_action = new Bash(cur_boy);//綁定男孩
	cur_bash_action->personType();
	cur_bash_action->personAction();

	return 0;
}

複製代碼
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息