作用

在不改变原有对象的基础上,将功能附加到对象上
提供比继承更有的弹性替代方案,扩展原有对象功能
动态的给对象添加功能,并动态的撤销
是继承的有力补充

Demo设计

假设有一个煎饼,可以加鸡蛋,火腿等,在不改变煎饼类的情况下对煎饼对象加更多的料

定义一个接口

显示煎饼的信息和价格

  1. public interface BatterCake {
  2. String getDesc();
  3. int cost();
  4. }

被装饰的对象

实现接口,表示为原味煎饼,什么料都不加

  1. public class BatterCakeNormal implements BatterCake {
  2. @Override
  3. public String getDesc() {
  4. return "煎饼";
  5. }
  6. @Override
  7. public int cost() {
  8. return 6;
  9. }
  10. }

装饰者抽象类

由于可以使用多个装饰者对对象进行修饰,所以需要先创建一个抽象类,要实现接口
为什么要使用抽象类呢,可以用于子类在装饰的时候必须要做一个操作

  1. public abstract class BaseDecorator implements BatterCake {
  2. /**
  3. * 用来注入
  4. */
  5. private final BatterCake batterCake;
  6. public BaseDecorator(BatterCake batterCake) {
  7. this.batterCake = batterCake;
  8. }
  9. protected abstract void doSomething();
  10. @Override
  11. public String getDesc() {
  12. return this.batterCake.getDesc();
  13. }
  14. @Override
  15. public int cost() {
  16. return this.batterCake.cost();
  17. }
  18. }

装饰者类

比如煎饼可以加鸡蛋,创建一个鸡蛋装饰者类,继承装饰者父类,重写父类的有参构造方法

  1. public class EggDecorator extends BaseDecorator {
  2. public EggDecorator(BatterCake batterCake) {
  3. super(batterCake);
  4. }
  5. @Override
  6. public String getDesc() {
  7. return super.getDesc() + "再加一个蛋";
  8. }
  9. @Override
  10. public int cost() {
  11. return super.cost() + 1;
  12. }
  13. }

比如煎饼可以加火腿,再写一个火腿装饰者类

  1. public class SausageDecorator extends BaseDecorator {
  2. public SausageDecorator(BatterCake batterCake) {
  3. super(batterCake);
  4. }
  5. @Override
  6. public String getDesc() {
  7. return super.getDesc() + "再加一根火腿";
  8. }
  9. @Override
  10. public int cost() {
  11. return super.cost() + 2;
  12. }
  13. }

使用装饰者模式

可以无限装饰,每装饰一次都需要new一次对象

  1. public static void main(String[] args) {
  2. //先定义一个不加料的煎饼
  3. BatterCake batterCake = new BatterCakeNormal();
  4. //开始装饰
  5. batterCake = new EggDecorator(batterCake);
  6. batterCake = new EggDecorator(batterCake);
  7. batterCake = new SausageDecorator(batterCake);
  8. batterCake = new SausageDecorator(batterCake);
  9. System.out.println(batterCake.getDesc() + ":" + batterCake.cost());
  10. }

运行结果为
image.png

小结

每加一个装饰的操作就需要新建一个装饰者类
不能摆脱继承,只是在继承的基础上增强