装饰模式

       装饰模式即为在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

      主要特点为:

(1) 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
(2) 装饰对象包含一个真实对象的引用(reference)
(3) 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
(4) 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。
举个例子:用控制台程序,写可以给别人搭配服装的代码。在对之间几种模式了解的情况下,写了如下代码:
#include <iostream>
#include <string>
using namespace std ;

class Person     //Person类
{
	string strname  ;
public:
	Person(string strname)
	{
		this->strname = strname ;
	}

	void Show_myself()
	{
		cout<<"装扮的"<<strname<<endl ; 
	}
};

class Finery    //服饰类
{
public:
	virtual void Show_myself() 
	{
		NULL ;
	}
};

class Tshirts : public Finery   //T恤衫类
{
public:
	void Show_myself()
	{
		cout<<"T恤衫  " ;
	}
};

class Jean : public Finery   //牛仔裤类
{
public:
	void Show_myself()
	{
		cout<<"牛仔裤  " ;
	}
};

class Shoes : public Finery   //鞋类
{
public:
	void Show_myself()
	{
		cout<<"鞋  " ;
	}
};

class Hat : public Finery   //帽子类
{
public:
	void Show_myself()
	{
		cout<<"帽子  " ;
	}
};

class Tie : public Finery   //领带类
{
public:
	void Show_myself()
	{
		cout<<"领带  " ;
	}
};

int main()
{
	Person * pPerson = new Person("perfect--顾") ;
	cout<<"装扮:" ;
	Finery * pTshirts = new Tshirts() ;
	Finery * pTie = new Tie() ;		
	Finery * pJean = new Jean() ;

	pTshirts->Show_myself() ;
	pTie->Show_myself() ;
	pJean->Show_myself() ;
	pPerson->Show_myself() ;
	
	return 0 ;

}
运行程序后:


      代码基本上符合题意,如果需要再添加如外套之类的新装扮,便可直接创建一个子类继承服饰类,并且符合开放—封闭原则,但是这样写宛如在众目睽睽之下一件件的穿衣服,不够合理,因此我们需要在内部就将衣服穿好,然后再显示出来,也许会觉得这和建造者模式类似,其实并不是,建造者模式要求建造的过程必须是稳定的,而现在这个例子,建造过程并不稳定,穿衣服有很多种搭配,换句话说,通过服饰组合出一个有个性的人有无数种方法,所以这里我们可以用装饰模式来实现。

      装饰模式的结构图:


用装饰模式写的代码:

#include <iostream>
#include <string>
using namespace std ;

class Person     //Person类
{
	string strname  ;
public:
	Person(){} ;
	Person(string strname)
	{
		this->strname = strname ;
	}

	virtual void Show_myself()
	{
		cout<<"装扮的"<<strname<<endl ; 
	}
};

class Finery  : public  Person//服饰类
{
	Person * pPerson ;
public:
	void decorate(Person * pPerson)   //传入对象指针
	{
		this->pPerson = pPerson ;
	}

	void Show_yourself() 
	{
		if(pPerson != NULL)
		{
			pPerson->Show_myself() ;   //当对象指针不为空的时候,调用Show_myself()函数
		}		
	}
};

class Tshirts : public Finery   //T恤衫类
{
public:
	void Show_myself()
	{
		cout<<"T恤衫  " ;
		Finery :: Show_yourself() ;     //调用基类的Show_myself函数  输出人名 用域解析符 防止造成命名冲突
	}
};

class Jean : public Finery   //牛仔裤类
{
public:
	void Show_myself()
	{
		cout<<"牛仔裤  " ;
		Finery :: Show_yourself() ;     //调用基类的Show_myself函数  输出人名 用域解析符 防止造成命名冲突
	}
};

class Tie : public Finery   //领带类
{
public:
	void Show_myself()
	{
		cout<<"领带  " ;
		Finery :: Show_yourself() ;     //调用基类的Show_myself函数  输出人名 用域解析符 防止造成命名冲突
	}
};

int main()
{
	Person * pPerson = new Person("perfect--顾") ;
	cout<<"装扮:" ;
	Tshirts * pTshirts = new Tshirts() ;   //定义Tshirts实例
	Tie * pTie = new Tie() ;		       //定义Tie实例
	Jean * pJean = new Jean() ;            //定义Jean实例

	pTshirts->decorate(pPerson) ;
	pTie->decorate(pTshirts) ;
	pJean->decorate(pTie) ;
	pJean->Show_myself() ;
	
	return 0 ;

}
运行后:



      以下情况适合使用装饰模式:

1. 需要扩展一个类的功能,或给一个类添加附加职责。
2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值