装饰者模式

Posted teiba

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰者模式相关的知识,希望对你有一定的参考价值。

 

装饰者模式:动态的将额外的责任添加到对象上去,相对于继承,提供更加灵活的扩展方案。

装饰者模式,有4个抽象的类概念:

  1. 抽象构建类:被装饰对象的接口
  2. 具体的构建类:被装饰的对象
  3. 抽象装饰者:怎么进行装饰的接口
  4. 具体装饰者:具体装饰的对象

关系类图如下:

技术图片

其中重点是:抽象装饰者接口继承了被装饰对象的接口,这点非常重要,它是能够进行动态装饰的关键,根据接口动态的去匹配具体构件类。

 

举例:
咖啡店原本提供有2种咖啡:CoffeeDarked深焙咖啡、CoffeeMixed混合咖啡,先需要在这2中咖啡中可以添加:Milk牛奶、Mocha摩卡。
思考:

技术图片

按照上图分析结果,可以调出6中不同口味的咖啡。如果按照继承的逻辑,一种咖啡可能需要建立一个子类(或者实现类),此处就需要建6个子类。如果需要添加的不止牛奶和摩卡2种,那子类将非常庞大。

如果使用装饰者模式,就不需要建立6个子类,只需要建立2种具体装饰者类(Milk、Mocha),即可满足需求。

下面是代码实现:()
1)抽象构件类

 1 /**
 2  * 抽象构件类
 3  * @author Administrator
 4  *
 5  */
 6 public interface Coffee {
 7   /**
 8    * 描述什么样的咖啡
 9    * @return
10    */
11   public abstract String getDescription();
12   
13   /**
14    * 计算咖啡的价格
15    * @return
16    */
17   public abstract double count();
18 }

2)具体构件类

 1 /**
 2  * 具体构件类:深焙咖啡
 3  * @author Administrator
 4  *
 5  */
 6 public class CoffeeDarked implements Coffee {
 7 
 8   @Override
 9   public String getDescription() {
10     return "深焙咖啡";
11   }
12 
13   @Override
14   public double count() {
15     return 10;
16   }
17 }
 1 /**
 2  * 具体构建类:混合咖啡
 3  * @author Administrator
 4  *
 5  */
 6 public class CoffeeMixed implements Coffee {
 7 
 8   @Override
 9   public String getDescription() {
10     return "混合咖啡";
11   }
12 
13   @Override
14   public double count() {
15     return 20;
16   }
17 }

3)抽象装饰者类

 1 /**
 2  * 咖啡装饰者接口
 3  * @author Administrator
 4  *
 5  */
 6 public interface DecoratorCoffee extends Coffee {
 7 
 8   public abstract String getDescription();
 9   
10 }

4)具体装饰者类

 1 /**
 2  * 具体装饰者:加牛奶
 3  * @author Administrator
 4  *
 5  */
 6 public class DecoratorMilk implements DecoratorCoffee {
 7   
 8   private Coffee coffee;
 9   
10   public DecoratorMilk(Coffee coffee){
11     this.coffee = coffee;
12   }
13 
14   @Override
15   public double count() {
16     
17     return coffee.count() + 5;
18   }
19 
20   @Override
21   public String getDescription() {
22     return coffee.getDescription() + "加牛奶";
23   }
24 }
 1 /**
 2  * 具体装饰者类:加摩卡
 3  * @author Administrator
 4  *
 5  */
 6 public class DecoratorMocha implements DecoratorCoffee {
 7   
 8   private Coffee coffee;
 9   
10   public DecoratorMocha(Coffee coffee){
11     this.coffee = coffee;
12   }
13 
14   @Override
15   public String getDescription() {
16     return coffee.getDescription() + "加摩卡";
17   }
18 
19   public double count() {
20     return coffee.count() + 2;
21   }
22 }

最后测试下:

 1 public class DecoratorTest {
 2 
 3   /**
 4    * @param args
 5    */
 6   public static void main(String[] args) {
 7     
 8     //想要一杯混合咖啡
 9     Coffee coffee1 = new CoffeeMixed();
10     System.out.println(coffee1.getDescription() + " " + coffee1.count());
11     
12     // 想要一杯加牛奶的混合咖啡(对coffee1进行装饰,加上牛奶)
13     Coffee coffee2 = new DecoratorMilk(coffee1);
14     System.out.println(coffee2.getDescription() + " " + coffee2.count());
15     
16     // 想要一杯加摩卡加牛奶的深焙咖啡
17     Coffee coffee3 = new CoffeeDarked();
18     coffee3 = new DecoratorMilk(coffee3);
19     coffee3 = new DecoratorMocha(coffee3);//进一步对加了牛奶的咖啡加上摩卡
20     System.out.println(coffee3.getDescription() + " " + coffee3.count());
21   }
22 }

测试结果:

技术图片

 

总结:
装饰者模式能实现动态的对对象进行扩展,主要有2点,一是,抽象装饰者类和具体的构建类有相同的接口,二是具体的装饰者类和抽象构建类之间有依赖(具体在UML中怎么称呼不太了解,之后在补习下),并且通过构造器依赖注入,在运行时,就根据具体的实现类注入了。这样就实现了对象动态扩展。

装饰者模式和代理模式的区别:
代理模式:给对象创建一个代理对象,由代理对象代替对象进行操作。
装饰者模式:给对象创建一个装饰类对象,对对象进行功能的扩展。

以上是关于装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式之装饰者模式

设计模式整理_装饰者模式

设计模式-装饰者模式(Go语言描述)

设计模式-装饰者模式(Go语言描述)

装饰者模式

设计模式 之 装饰者模式