装饰者模式

定义

在不改变原有对象的基础之上,将功能附加到对象上。提供了比继承更有弹性的替代方案(扩展原有对象功能)

为什么要使用装饰者模式

如下图:我们的纯豆浆,可以搭配红糖,变成红糖豆浆,也可以搭配红豆变成红豆豆浆,同时也可以红糖配红豆一起组成红糖红豆豆浆,那如果我们每次有一个新的配料加入,我们就写一个新的类,将会导致我们的类无限多,类爆炸了,这个时候装饰者模式起作用了。

装饰者模式的结构

  • 抽象组件(Component):给出一个抽象接口,以规范准备接收附加责任的对象(本文例子中为Drink 饮品对象)
  • 被装饰者(ConcreteComponent):抽象组件(Component)的具体实现,也就是我们要装饰的具体对象(本文例子中为Soya豆浆对象)
  • 装饰者(Decorator)组件:持有抽象组件(Component)的实例引用,该类的职责就是为了装饰具体组件对象定义的基类(本文例子中为Decorator 装饰器对象)
  • 具体装饰(ConcreteDecorator):负责给构建对象装饰附加功能(本文中例子,就是红豆装饰豆浆)


具体代码

抽象组件(Component) Drink 饮品

  1. package com.bowen;
  2. public interface Drink {
  3. //抽象组件
  4. public String desc();
  5. public double money();
  6. }

被装饰者(ConcreteComponent) Soya 豆浆

  1. package com.bowen;
  2. public class Soya implements Drink {
  3. //被装饰者
  4. @Override
  5. public String desc() {
  6. return "纯豆浆";
  7. }
  8. @Override
  9. public double money() {
  10. return 5;
  11. }
  12. }

装饰者(Decorator)组件 Decorator

  1. package com.bowen;
  2. public abstract class Decorator implements Drink{
  3. //装饰器
  4. //1.抽象类
  5. //2.实现抽像组件接口
  6. //3.持有抽象接口引用
  7. //定义私有的饮品接口
  8. private Drink drink;
  9. public Decorator(Drink drink){
  10. this.drink = drink;
  11. }
  12. @Override
  13. public String desc() {
  14. return this.drink.desc();
  15. }
  16. @Override
  17. public double money() {
  18. return this.drink.money();
  19. }
  20. }

具体装饰(ConcreteDecorator) 这里是红豆

  1. package com.bowen;
  2. public class RedBean extends Decorator {
  3. public RedBean(Drink drink){
  4. super(drink);
  5. }
  6. @Override
  7. public String desc() {
  8. return super.desc() + "+红豆";
  9. }
  10. @Override
  11. public double money() {
  12. return super.money() + 4.2;
  13. }
  14. }

测试代码

  1. package com.bowen;
  2. public class Test {
  3. public static void main(String[] args) {
  4. Drink soya = new Soya();//新建豆浆
  5. Drink redbean = new RedBean(soya); //加入红豆,生产红豆豆浆
  6. System.out.println(redbean.desc());
  7. System.out.println(redbean.money());
  8. }
  9. }
  10. 结果:
  11. 纯豆浆+红豆
  12. 9.2

优缺点

  1. 优点
  • 提供比继承更好的灵活性,装饰是动态的,运行时可以修改,继承是静态的,编译期间已确定好。
  • 通过使用不同的装饰类及他们的排列组合,可以创造出许多不同行为的组合。
  1. 缺点
  • 容易产生许多小对象,大量的小对象占用内存
  • 组合方式过多不好管理,容易出错

参考慕课网视频

慕课网-装饰者模式