大話設計模式C++版本-03-裝飾模式

概念

裝飾模式:動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾器模式相比生成子類更爲靈活。
允許向一個現有的對象添加新的功能,同時又不改變其結構
優點:裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能。
缺點:多層裝飾比較複雜。

應用場景

  1. 在不想增加很多子類的情況下擴展類。
  2. 動態增加功能,動態撤銷。

一般步驟

  1. 定義一個基類,並帶有一個功能的函數。如:Person類裏有個Show()功能;
    class Person
    {
    public:
    	Person(){};
    	Person(string name)
    	{
    		this->name = name;
    	}
    	~Person() {}
    	virtual	void Show() // 展示裝扮
    	{
    		cout << "裝扮的" << name <<  endl;
    	}
    private:
    	string name;
    };
    
  2. 定義一個裝飾類,繼承前面的基類,並且有一個裝飾的函數可以裝飾基類的指針,且重寫基類的那個功能函數(Show),並在函數裏調用基類的功能函數(Show);
    這一步非常關鍵,是這個模式裏最重要的一步
    class Finery : public Person // 裝飾類
    {
    public:
    	void Decorate(Person* person) // 裝扮指定的人,在這個模式裏最重要的一個函數
    	{
    		boy = person;
    	}
    	void Show()
    	{
    		if (boy)
    		{
    			boy->Show();
    		}
    	}
    private:
    	Person*	boy;
    };
    
  3. 定義具體的功能類,繼承前面的裝飾類,且重寫功能函數(Show);
    class TShirt : public Finery
    {
    public:
    	void Show()
    	{
    		printf("Tshirt ");
    		Finery::Show();
    	}
    };
    class BigTrouser : public Finery
    {
    public:
    	void Show()
    	{
    		printf("BigTrouser ");
    		Finery::Show();
    	}
    };
    

完整實例

#include <cstdio>
#include <iostream>
#include <string>

using namespace std;

class Person
{
public:
	Person(){};
	Person(string name)
	{
		this->name = name;
	}
	~Person() {}

	virtual	void Show() // 展示裝扮
	{
		cout << "裝扮的" << name <<  endl;
	}
	
private:
	string name;
};

class Finery : public Person // 裝飾類
{
public:
	void Decorate(Person* person) // 裝扮指定的人,在這個模式裏最重要的一個函數
	{
		boy = person;
	}
	
	void Show()
	{
		if (boy)
		{
			boy->Show();
		}
	}

private:
	Person*	boy;
};

class TShirt : public Finery
{
public:
	void Show()
	{
		printf("Tshirt ");
		Finery::Show();
	}
};

class BigTrouser : public Finery
{
public:
	void Show()
	{
		printf("BigTrouser ");
		Finery::Show();
	}
};

int main()
{
	Person *xc = new Person("小菜");
	
	cout << "第一鍾裝扮" << endl;
	
	TShirt *tshirt = new TShirt();
	BigTrouser  *BigTrouser  = new BigTrouser();
	
	tshirt->Decorate(xc);  // 用T恤裝扮小菜
	BigTrouser->Decorate(tshirt); // 用褲子 裝扮 "已裝扮了T恤" 的小菜
	BigTrouser->Show();
	
	return 0;
}

參考資料

程傑老師的《大話設計模式》
裝飾器模式|菜鳥教程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章