大话设计模式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;
}

参考资料

程杰老师的《大话设计模式》
装饰器模式|菜鸟教程

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