现在的位置: 首页 > 综合 > 正文

装饰者模式

2012年12月17日 ⁄ 综合 ⁄ 共 1752字 ⁄ 字号 评论关闭

 想象一下有如下的场景:

image

    有两种主咖啡, 可以搭配任意的饮料,我们的目标是允许类容易扩展,在不修改现有代码的情况下,可以搭配新的行为。这里可以用装饰者模式来实现。

1. uml 图

    装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

image

    这里吹一下装饰者模式的好处:

  • 每个组件都可以单独使用,或者被装饰者包装起来使用
  • 装饰者可以扩展组件的状态
  • 装饰可以加上新的方法
  • 可以为组件添加新的方法而用修改装饰者,反之亦可

2. 代码示例

    首先构造基类

1 class Beverage
2 {
3  public:
4 virtual int cost() = 0;
5 };

    然后 定义组件, 这里定义了两个 Blend 和 DarkRoast

复制代码
1 class Blend : public Beverage
2 {
3  public:
4 int cost()
5 {
6 return 1;
7 }
8 };
复制代码
复制代码
1 class DarkRoast : public Beverage
2 {
3  public:
4 int cost()
5 {
6 return 2;
7 }
8 };
复制代码

    下一步就定义 装饰者, 这里定义了3个, 所有的装饰者都是从Decorator 类继承的

复制代码
1 class Decorator : public Beverage
2 {
3  public:
4 int cost()
5 {
6 return observed_->cost() + 0;
7 }
8 void setObserver(shared_ptr<Beverage> observed)
9 {
10 observed_ = observed;
11 }
12
13  protected:
14 shared_ptr<Beverage> getObserver()
15 {
16 return observed_;
17 }
18
19  private:
20 shared_ptr<Beverage> observed_;
21 };
22
23  class Milk : public Decorator
24 {
25  public:
26 int cost()
27 {
28 return getObserver()->cost() + 1;
29 }
30 };
31
32  class Mocha : public Decorator
33 {
34  public:
35 int cost()
36 {
37 return getObserver()->cost() + 2;
38 }
39 };
40 class Soy : public Decorator
41 {
42 public:
43 int cost()
44 {
45 return getObserver()->cost() + 3;
46 }
47 };
复制代码

    最后看下测试代码

复制代码
1 int _tmain(int argc, _TCHAR* argv[])
2 {
3
4 shared_ptr<Beverage> blendObserved(new Blend()) ;
5 shared_ptr<Beverage> darkObserved(new DarkRoast());
6
7 shared_ptr<Decorator> blendWithMilk(new Milk());
8 blendWithMilk->setObserver(blendObserved);
9
10 shared_ptr<Decorator> blendWithMocha(new Mocha());
11 blendWithMocha->setObserver(blendObserved);
12
13 shared_ptr<Decorator> blendWithSoy(new Soy());
14 blendWithSoy->setObserver(blendObserved);
15
16 cout<<blendWithMilk->cost()<<endl;
17 cout<<blendWithMocha->cost()<<endl;
18 cout<<blendWithSoy->cost()<<endl;
19 return 0;
20 }
复制代码

3. 总结

    开放关闭原则: 对扩展开放,对修改关闭。

  • 继承属于扩展形式之一,但不见得是达到弹性设计的最佳方式
  • 在我们的设计中,应该允许行为可以被扩展,而无需修改实现
  • 除了继承,装饰者模式也可以让我们扩展行为,而装饰者模式意味着一群装饰者类来包装具体的组件。
  • 装饰者会导致设计中出现许多小对象,如果过度使用会是程序变得复杂。

抱歉!评论已关闭.