• 装饰模式Decorator


    意图

          动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。

    装饰模式的本质是动态组合。动态是手段,组合是目的。每个装饰类可以只负责添加一项额外功能,然后通过组合为被装饰类添加复杂功能。由于每个装饰类的职责比较简单单一,增加了这些装饰类的可重用性,同时也更符合单一职责原则。

    适用环境

    (1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

    (2)处理那些可以撤消的职责。

    (3)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的 子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

    角色

        l 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象

        l 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类

        l 装饰角色(Decorator):持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口

        l 具体装饰角色(ConcreteDecorator):负责给构件对象“贴上”附加的责任

    类图

    实例

    1抽象接口:

    1.1饮料:

    public interface Beverage {
        public String getDesc();
    
        public double getPrice();
    }

    2接口实现:

    2.1奶茶:

    public class Milktea implements Beverage {
        @Override
        public String getDesc() {
            System.out.println("--Milktea.desc");
            return "奶茶";
        }
    
        @Override
        public double getPrice() {
            System.out.println("--Milktea.price");
            return 10;
        }
    }

    2.2奶绿:

    public class Milkgreen implements Beverage {
        @Override
        public String getDesc() {
            System.out.println("--Milkgreen.desc");
            return "奶绿";
        }
    
        @Override
        public double getPrice() {
            System.out.println("--Milkgreen.price");
            return 8;
        }
    }

     3装饰类:装饰者类内有一个真实对象的引用

    public class Decorator implements Beverage {
    
        private Beverage beverage = null;
    
        public Decorator(Beverage beverage) {
            System.out.println("--Decorator.construct");
            this.beverage = beverage;
        }
    
        @Override
        public String getDesc() {
            System.out.println("--Decorator.desc");
            return beverage.getDesc();
        }
    
        @Override
        public double getPrice() {
            System.out.println("--Decorator.price");
            return beverage.getPrice();//价格 子类决定
        }
    }

     4继承装饰类(覆盖父类方法):

    4.1红豆:

    public class Redbean extends Decorator {
        private String desc = "加了红豆";
    
        public Redbean(Beverage beverage) {
            super(beverage);
        }
    
        public String getDesc() {
            System.out.println("--Redbean.desc");
            return super.getDesc() + desc + "的价钱:";
        }
    
        public double getPrice() {
            System.out.println("--Redbean.price");
            return super.getPrice() + 2;  //2表示红豆的价格
        }
    }

    4.2布丁:

    public class Pudding extends Decorator {
        private String desc = "加了布丁";
    
        public Pudding(Beverage beverage) {
            super(beverage);
        }
    
        public String getDesc() {
            System.out.println("--Pudding.desc");
            return super.getDesc() + desc + "的价钱:";
        }
    
        public double getPrice() {
            System.out.println("--Pudding.price");
            return super.getPrice() + 1;//1表示布丁的价格
        }
    }

    5测试:

    public class Test {
        public static void main(String[] args) {
            Beverage beverage = new Milktea();
            Redbean redbean = new Redbean(beverage);
            System.out.println(redbean.getDesc() + "
    " + redbean.getPrice());
            Beverage rb = new Redbean(beverage);
            Beverage pb = new Pudding(rb);
            System.out.println(pb.getDesc() + "
    " + pb.getPrice());//混合
        }
    }

    6结果:

    --Decorator.construct
    --Redbean.desc
    --Decorator.desc
    --Milktea.desc
    --Redbean.price
    --Decorator.price
    --Milktea.price
    奶茶加了红豆的价钱:
    12.0
    --Decorator.construct
    --Decorator.construct
    --Pudding.desc
    --Decorator.desc
    --Redbean.desc
    --Decorator.desc
    --Milktea.desc
    --Pudding.price
    --Decorator.price
    --Redbean.price
    --Decorator.price
    --Milktea.price
    奶茶加了红豆的价钱:加了布丁的价钱:
    13.0

    JDK运用

    JDK中的装饰者模式:java.io

    FilterInputStream继承(实现)InputStream,同时BufferedInputStream继承了FilterInputStream

    1. 抽象构件:最顶层的基类InputStream(饮料)
    2. 具体构件:FileInputStream和ObjectInputStream等(奶茶)
    3. 装饰角色:FilterInputStream中有一个InputStream的实例和构造方法传入InputStream对象(装饰器)
      public class FilterInputStream extends InputStream {
      
          protected volatile InputStream in;
      
          protected FilterInputStream(InputStream in) {
              this.in = in;
          }
    4. 具体装饰角色:BufferedInputStream中有构造方法传入InputStream对象,实现了装饰(红豆)
          public BufferedInputStream(InputStream in) {
              this(in, defaultBufferSize);
          }
      
          public BufferedInputStream(InputStream in, int size) {
              super(in);
              if (size <= 0) {
                  throw new IllegalArgumentException("Buffer size <= 0");
              }
              buf = new byte[size];
          }

    Head First 设计模式(中文版)的示例:

    码云地址:https://gitee.com/manusas/DecoratorDP

  • 相关阅读:
    任务信息的高级选项(Project)
    延时间隔(Project)
    在【自定义列】中使用M函数(Power Query 之 M 语言)
    在对话框中设置前置任务(Project)
    前置任务(Project)
    拖动条形图设置任务关联(Project)
    2020最新移动,联通,电信号码正则
    2019最新移动,联通,电信号码正则
    原生js判断手机端页面滚动停止
    win10下vue-devtools的安装和使用
  • 原文地址:https://www.cnblogs.com/manusas/p/6722964.html
Copyright © 2020-2023  润新知