代码改变世界

设计模式(3)--装饰模式

2016-11-02 01:07  sylar_liang  阅读(211)  评论(0编辑  收藏  举报
//单一原则: 一个类而言,应该仅有一个引起它变化的原因。
//开放-封闭原则: 类/模块/函数等等,应该可以扩展,但是不可修改。
//依赖倒装原则: 抽象不应该依赖细节,洗劫应该依赖于抽象。换句话说是,要针对接口编程,不要对实现编程。
//A.高层模块不应该依赖低层模块。两个都应该依赖抽象。
//B.抽象不应该依赖细节。细节应该依赖抽象。
//里氏代换原则: 子类型必须能够替换掉它们的父类型。

 

//3.装饰模式
//ver1
class Person
{
private:
	string _name;
public:
	Person(string name)
	{
		_name = name;
	}
	void Show()
	{
		//...
	}
};

//服饰抽象类
class Finery
{
public:
	virtual void Show() = 0;
};

//T恤类
class TShirts : public Finery
{
public:
	virtual void Show()
	{
		//..
	}
};

//垮裤类
class BigTrouser : public Finery
{
public:
	virtual void Show()
	{
		//..
	}
};

//领带类
class Tie : public Finery
{
public:
	virtual void Show()
	{
		//..
	}
};

void main11()
{
	Person *ppc = new Person("fun");
	TShirts *pd1 = new TShirts();
	BigTrouser *pd2 = new BigTrouser();
	Tie *pd3 = new Tie();

	//装扮1
	pd1->Show();
	pd2->Show();
	ppc->Show();
	//装扮2
	pd1->Show();
	pd3->Show();
	ppc->Show();
	//缺点: 一个一个显示出来; 组装应该在内部进行; 
}

 

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

 

//3.装饰模式
//ver2

//Component是定义一个对象接口,可以给这些对象动态地添加职责。
//ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责。
//Decorator抽象装饰类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,无需知道Decorator的存在;
//ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

class Component
{
public:
	virtual void Operation() = 0; //接口
};

class ConcreteComponent : public Component
{
	virtual void Operation()
	{
		//...
	}
};

class Decorator : public Component
{
protected:
	Component *pcomponent;
public:
	void SetComponent(Component *pcom)
	{
		pcomponent = pcom;
	}
	virtual void Operation()
	{
		if (pcomponent != NULL)
		{
			pcomponent->Operation();
		}
	}
};

class ConcreteDecoratorA : public Decorator
{
private:
	string addState;
public:
	virtual void Operation()
	{
		Decorator::Operation(); //先运行Component的Operation,再执行本类的操作。
		addState = "New State";
		//...
	}
};

class ConcreteDecoratorB : public Decorator
{
private:
	void AddBehavior() //本类独有的操作;
	{
		//...
	}
public:
	virtual void Operation()
	{
		Decorator::Operation();
		AddBehavior();
	}
};

void main12()
{
	ConcreteComponent * pc = new ConcreteComponent();
	ConcreteDecoratorA * d1 = new ConcreteDecoratorA();
	ConcreteDecoratorB * d2 = new ConcreteDecoratorB();

	d1->SetComponent(pc); //先用 ConcreteDecoratorA 来包装 ConcreteComponent; 会执行 ConcreteComponent::Operation()
	d2->SetComponent(d1); //再用 ConcreteDecoratorB 来包装 ConcreteDecoratorA
	d2->Operation(); //最终执行 d2->Operation()
	//装饰模式是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了。
	//每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。
}

 

//如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
//如果只有一个ConcreteDecorator类,那么久没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合成一个类.

 

 

//3.装饰模式
//ver3
class Person
{
private:
	string _name;
public:
	Person(){} //用于 TShirts 等派生类构造默认的构造函数;
	Person(string name)
	{
		_name = name;
	}
	virtual void Show()
	{

	}
};

//服饰类
class Finery : public Person
{
protected:
	Person component;

public:
	void Decorate(Person comp)
	{
		component = comp;
	}

	virtual void Show()
	{
		component.Show();
	}
};

//具体服饰类
class TShirts : public Finery
{
public:
	virtual void Show()
	{
		//do something
		Finery::Show();
	}
};

class BigTrouser : public Finery
{
public:
	virtual void Show()
	{
		//do something.
		Finery::Show();
	}
};

void main31()
{
	Person * ppc = new Person("fun");

	TShirts * pd1 = new TShirts();
	BigTrouser * pd2 = new BigTrouser();

	pd1->Decorate(*ppc);
	pd2->Decorate(*pd1);
	pd2->Show();
}

 

//装饰模式是为已有功能动态地添加更多功能的一种方式。
//装饰模式把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象。
//优点: 把类中的装饰功能从类中搬移去除,这样可以简化原有的类。
// 有效地把类的核心职能和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑。