设计模式之装饰模式

意图:动态的给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活。
动机:为某个对象而不是整个类添加一些功能。
适用性:
在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责。
处理那些可以撤销的职责。
当不能采用生产子类的方法进行扩充时。一种情况是有大量独立的扩展,为支持每一种组合奖产生大量的子类,使得子类数目呈爆炸性增长。另一种情况是因为类定义被隐藏,或类定义不能用于生成子类。
结构:


Component:定义一个对象接口,可以给这些对象动态地添加指责。
ConcreteComponent:定义一个对象,可以给这个对象添加一些指责。通常是被装饰对象的原始对象。
Decorator:维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
对于Compoment来说,无需知道Decorator的存在

ConcreteDecorator:向组件添加指责。

但是被装饰的对象不一定是原始的那个对象了,也可能是被其他装饰起装饰过后的对象,因为都是同样的接口,也就是同一类型。

协作:
Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加的动作。

效果:

两个优点

1 比静态继承更灵活。2 避免在层次结构高层的类有太多的特征。

两个缺点:

3 Decorator与它的Component不一样。4 有许多小对象。
用一个装饰可以改变对象的外表。Strategy模式可以改变对象的内核。

实现:

1 接口的一致性,装饰对象的接口与这个所装饰的component的接口是一致的,两个类有一个共同的父类。

2 省略抽象的decorator类,如果仅需要添加一个职责,则可以省略抽象的decorator类

3 保持component的简单性。因为这个是装饰类和组件类的基类,所以它应该尽量简单,应集中定义接口而不是存储数据。对数据的定义应延迟到子类。

4 改变对象外壳和改变对象内核:decorator可以看作对象的外壳,可以改变对象的行为。另一种是改变对象内核,如策略模式。

当component原本就很大,使用decorator代价太高,strategy相对好些,因为这里面组建将它的行为转发给一个独立的策略对象。自己可以动态替换策略对象,从而改变。

两者区别:

decorator:仅从外部改变组建,所以组件无须对装饰有了解,即这些装饰队该组件是透明的。接口必须与组件相同。


strategy模式:component组建本身知道进行什么扩充,而且必须引用并维护相应的策略。策略可以有自己的接口。


装饰模式是在已有的功能动态的添加更多功能的一种方式。

适用情况:当系统需要新功能的时候,向旧的类中添加新的代码。这些新代码通常装饰了原有类的核心职责或主要行为。它们在主类中加入新的字段,新的方法和新的逻辑,从而增加了主类的复杂度。而这些新加的动态仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。装饰模式提供了一个好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择的,按顺序地使用装饰功能包装对象了。

装饰模式把类中的装饰功能从类中搬移去除,这样简化原有的类,把类的核心指责和装饰功能区分开了。有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的修饰逻辑。

装饰的实现,相当于递归调用,一层装饰一层,最后到最底层,回调。

代码(大话设计模式上对应的例子):

//装饰模式:动态地给一个对象添加一些额外的职责,
//就增加功能来说,装饰模式比生成子类更加灵活
#ifndef DECORATOR_H
#define DECORATOR_H

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

//Component加ConcreteComponent
class Person
{
public:
	Person()
	{

	}

	Person(string name) : _name(name)
	{

	}

	string Name()
	{
		return _name;
	}

	virtual void Show()
	{
		cout << "装扮的" << _name << endl;
	}
protected:
private:
	string _name;
};

//装饰类
class Finery : public Person
{
public:
	void Decorate(Person& component)
	{
		_component = &component;
	}

	void Show()
	{
		if (_component != NULL)
		{
			_component->Show();
		}
	}
protected:
	Person *_component;
};

//具体服饰类
class TShirts : public Finery
{
public:
	void Show()
	{
		cout << "大T恤 ";
		Finery::Show();
	}
};

class BigTrouser : public Finery
{
public:
	void Show()
	{
		cout << "垮裤 ";
		Finery::Show();
	}
};

class Sneakers : public Finery
{
public:
	void Show()
	{
		cout << "破球鞋 ";
		Finery::Show();
	}
};

class Suit : public Finery
{
public:
	void Show()
	{
		cout << "西装 ";
		Finery::Show();
	}
};

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

class LeatherShoes : public Finery
{
public:
	void Show()
	{
		cout << "皮鞋 ";
		Finery::Show();
	}
};

#endif
#include "decorator.h"

int main()
{
	Person xc("小菜");

	cout << "第一种装扮:";
	Sneakers pqx;
	BigTrouser kk;
	TShirts* dtx = new TShirts;

	pqx.Decorate(xc);
	kk.Decorate(pqx);
	dtx->Decorate(kk);
	dtx->Show();

	cout << "\n第二种装扮:";
	LeatherShoes px;
	Tie ld;
	Suit *xz = new Suit;

	px.Decorate(xc);
	ld.Decorate(px);
	xz->Decorate(ld);
	xz->Show();

	delete dtx;
	dtx = NULL;
	delete xz;
	xz = NULL;

	system("pause");
	return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值