首页 > 代码库 > 设计模式之装饰模式 c++实现和详细分析

设计模式之装饰模式 c++实现和详细分析

Decorator模式(别名Wrapper):动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。 它使功能具有动态性

 

 已经开发完毕的对象,后期由于业务需要,对旧的对象需要扩展特别多的功能,这时候使用给对象动态地添加新的状态或者行为(即装饰模式)方法,而不是使用子类静态继承。

引入装饰模式的原因 

由于若有很多个功能,这么多功能 可能会出现各种组合,而每个组合都要对应一个类,这是指数级的类的数量增长(因为我们要扩展不应直接修改类,所以采取继承 而不是改变原有类)   这样会因为几个功能而需要添加很多类  如 per1 继承 A B C D 后变为产生类pa pb pc pd ,之后又出现了一个e  需要继续增加pe 继承出pae pbe pce pde 甚至pabcde pade 等等  这时就需要装饰模式了  动态的给一个对象增加额外的职责功能  它也可以解决部分的多继承问题 注意仅仅是部分


可能有人说将所有新功能加进原来的类中 但是不要忘记了我们设计的原则:尽量使用扩展而不使用改变 即开放封闭原则 所以我们不能简单的这样做

 此模式的最大优点是把类中的装饰功能从类中移除,简化了原来的类  有效的把核心职责和装饰功能分开,而且可以去除相关类中的重复的装饰逻辑

 



下面演示一个例子  关于坦克的  假设坦克可以有2种装饰 或者说功能  加大火力 和 消音   

/*******************************************
* 装饰者模式  演示   2014.5.12             *
* by hnust_xiehonghao                      *
********************************************/ 

#include <iostream>
using namespace std;

//坦克抽象类 component
class Tank 
{
public :

     virtual void shot()
	 {
		 cout <<  "向我开炮!"  <<  endl;
	 }
};

//Concrete Component  
class T50 :public Tank //具体的一种坦克 型号为T50 也可以有很多其它种类的坦克
{
public :
	void shot()
	{
		cout << "T50开炮" << endl;
	}
};

//Decorator   
class Decorator: public Tank//此处不应认为是is_a关系 而应该认为是like_a
{
protected:  //这里必须是protect哦  因为其它继承Decorator的类要用
	Tank *tank;//has_a的关系
	
public:
	void decorator(Tank *_tank)
	{
		this->tank = _tank;
	}
	void shot()
	{
		tank->shot();
	}
};


//DecoratorA  加大火力
class BigShot :public  Decorator  
{
	
public:
	void shot()
	{
		//为了死的安详,我想被大火力打死,另外请静音
		cout << "大火力准备完毕" <<endl;
		tank->shot();
		
	}
};


//DecoratorB     消音
class SilentShot :public Decorator   
{
	
public:
	void shot()
	{
			//为保证是被炮打死 而不是震死,请静音
		cout << "消音完毕" <<endl;
		tank->shot();
	} 
};

int main()
{
	Tank *ptank = new T50();
	Decorator *pDecorator = new Decorator();
	pDecorator->decorator(ptank);
	BigShot *pBig = new BigShot();
	pBig->decorator(pDecorator);
   	SilentShot *pBigSlient = new SilentShot();
	pBigSlient->decorator(pBig);
	pBigSlient->shot();

	return 0;
}

注意  模式设计是很自由的 而不一定要套上面的方法  网上也有很多其它方式的实现 ,  对于每一个模式 你使劲模仿也许它不是你要的模式 而改的面目全非的可能仍旧是那种模式   

上面代码是模仿 大话设计模式这本经典著作中的        

设计模式是很自由的 不是死板的 像如果只有一个createdecrator类(具体装饰类) 有时我们可以不要Decrator类  有时我们也可以不要comnent类



此图来自李建忠老师的视频系列教程: C#面向对象设计模式纵横谈系列课程  推荐大家看看  模式是抽象的 与语言无关  不要被c#吓住额 我也在看  
decorator的装饰过程有点像多继承,但这只是巧合,很多时候是不能用它实现多继承的 因为它并非是为解决多继承的问题而设计的
转载请注明 by hnust_xiehonghao