装饰模式

对原有对象进行装饰(Decorate),不用创造更多的具体的子类,而是通过独立的装饰类来扩展原对象的功能.

原有对象可能是核心类,保持核心类的简单,花哨的功能通过装饰类来添加和扩充,符合开闭原则.

2018-08-02-14-30-27

核心是 Decorator 有一指向 Component 的指针.

#include <string>
#include <iostream>

class Component {
	public :
		Component() = default;
		virtual ~Component(){}
		virtual void operation(){}
};

class ConcreteComponent : public Component {
	public:
		void operation() { std::cout << "ConcreteComponent operation." << std::endl;}
};

class Decorator : public Component {
	public:
		void set_deco_obj(Component *p) {ptr_component = p;}
	protected:
		Component* ptr_component;
};

class ConcreteDecorator : public Decorator {
	public:
		ConcreteDecorator(Component * c = NULL) {
			ptr_component = c;
		}
		void before() { std::cout << "deco before operation." << std::endl;}
		void after() { std::cout << "deco after operation." << std::endl;}
		void operation() {
			before();
			ptr_component->operation();
			after();
		}
};

int main(int argc, char* argv[])
{
	std::cout << "Before decoration..." <<std::endl;
	ConcreteComponent c;
	c.operation();

	std::cout << "After decoration..." <<std::endl;
	//半透明模式,在具体抽象构件里,调用自己的方法,如after
	ConcreteDecorator deco;
	deco.set_deco_obj(&c);
	deco.operation();
	deco.after();

	//透明装饰模式
	//使用抽象构建来定义对象.只使用抽象构建里定义的方法,如operation
	Component * cc  = new ConcreteDecorator(&c);
	cc->operation();

	return 0;
}

半透明和透明装饰模式的区别

所谓透明,即客户端完全针对抽象构件(Component)定义的方法(operation)编程,而且不应该将对象申明为具体的构件 or 装饰器类型,对于客户端来讲,都是 component.operation(),看不到区别.

Component * c = new ConcreteDecorator1();
c->operation();

Component * c = new ConcreteComponent2();
c->operation();

半透明模式,用户需要单独调用新增的方法.

ConcreteDecorator1 * c = new ConcreteDecorator1();
c->operation();
//额外方法,必须指向具体对象才能使用,基类指针不行.
c->extra();

没有抽象构件类的装饰模式

此时 Decorator 可以直接作为 ConcreteComponent 的子类.

2018-08-07-10-48-55