装饰者设计模式

装饰者设计模式


  1. 简单介绍

    装饰者模式是一种结构型设计模式。该模式能够动态的将新的功能附加(装饰)在某个类(被装饰者)的方法中。该模式能够很好的满足OCP原则。

  2. 使用场景

    项目开发过程中,需要对某个类的方法在已有功能的基础上进行一个增强。并且不希望该类原有代码进行修改。

  3. 场景举例

    JDK中有许多针对字节流传输的类(InputStream的子类),如:FileInputStream类等,该类是一个不带缓冲区的类,效率并不高。设计者为此引入了BufferedInputStream,持有FileInputStream对象,并引入缓冲区,来提高传输效率,从而达到一个增强的作用。其中FileInputStream是被装饰类,BufferedInputStream是装饰类。

  4. UML类图
    装饰者模式UML类图

  5. 具体实现

    • 描述

      • 被装饰者为相机类:佳能相机(CanonCamera)、尼康相机(NikonCamera)

      • 装饰者为镜头类:变焦镜头(ZoomLens)、定焦镜头(FixedFocusLens)

      • 相机在镜头的加持下(即装饰下),可以提高自己的像素。一个相机可以被多个镜头装饰,像素大小会进行叠加

      • CanonCamera 原生像素为1200W,NikonCamera 原生像素为800W

      • ZoomLens 可增加800W像素,FixedFocusLens 可增加1000W像素

    • 实现代码

      Photographable.java

      /**
       * 可拍照设备接口
       */
      public interface Photographable {
      
          /**
           * 获取拍照设备像素值
           * @return 像素值
           */
          int getPixel();
      }
      

      NikonCamera.java

      /**
       * 尼康相机
       */
      public class NikonCamera implements Photographable {
      
          /**
           * 尼康相机原生像素值为
           * @return 尼康相机像素值
           */
          @Override
          public int getPixel() {
              return 1400;
          }
      }
      

      CanonCamera.java

      /**
       * 佳能相机
       */
      public class CanonCamera implements Photographable {
      
          /**
           * 佳能相机原生像素值为
           * @return 佳能相机像素值
           */
          @Override
          public int getPixel() {
              return 1200;
          }
      }
      

      Lens.java

      /**
       * 镜头抽象类
       */
      public abstract class Lens implements Photographable {
      
          /**
           * 持有被装饰类引用
           */
          public Photographable photographable;
      
          public Lens(Photographable photographable) {
              this.photographable = photographable;
          }
      }
      

      ZoomLens.java

      /**
       * 装饰者:变焦镜头
       * 可以帮助拍照设备增加800W像素
       */
      public class ZoomLens extends Lens {
      
          /**
           * 变焦镜头自带800W像素
           */
          private final int pixel = 800;
      
          public ZoomLens(Photographable photographable) {
              super(photographable);
          }
      
          /**
           * 有了变焦镜头加持后的拍照设备的最终像素值
           * @return 最终像素值
           */
          @Override
          public int getPixel() {
              return photographable.getPixel() + this.pixel;
          }
      }
      

      FixedFocusLens.java

      /**
       * 装饰者:定焦镜头
       * 可以帮助拍照设备增加1000W像素
       */
      public class FixedFocusLens extends Lens {
      
          /**
           * 定焦镜头自带1000W像素
           */
          private final int pixel = 1000;
      
          public FixedFocusLens(Photographable photographable) {
              super(photographable);
          }
      
          /**
           * 有了定焦镜头加持后的拍照设备的最终像素值
           * @return 最终像素值
           */
          @Override
          public int getPixel() {
              return photographable.getPixel() + this.pixel;
          }
      }
      

      Client.java

      public class Client {
      
          public static void main(String[] args) {
      
              // 1.1 创建一台佳能相机
              Photographable canonCamera = new CanonCamera();
              // 1.2 输出佳能相机初始像素值
              System.out.println(String.format("佳能相机初始像素大小为:%s", canonCamera.getPixel()));
      
              // 1.3 给佳能相机一个变焦镜头进行加持
              Photographable canonCameraWithZoomLens = new ZoomLens(canonCamera);
              // 1.4 输出有了变焦镜头加持后的佳能相机的像素值
              System.out.println(String.format("变焦镜头加持后的佳能相机像素大小为:%s", canonCameraWithZoomLens.getPixel()));
      
              // 1.5 在佳能相机有一个变焦镜头进行加持的基础上,在给上一个定焦镜头的加持
              Photographable canonCameraWithZoomLensAndFixedFocusLens = new FixedFocusLens(canonCameraWithZoomLens);
              // 1.6 在佳能相机有一个变焦镜头进行加持的基础上,在给上一个定焦镜头进行叠加
              System.out.println(String.format("变焦镜头和定焦镜头加持后的佳能相机像素大小为:%s", canonCameraWithZoomLensAndFixedFocusLens.getPixel()));
      
              // 分割
              System.out.println("=========================");
      
              // 2.1 创建一台佳能相机
              Photographable nikonCamera = new NikonCamera();
              // 2.2 输出佳能相机初始像素值
              System.out.println(String.format("尼康相机初始像素大小为:%s", nikonCamera.getPixel()));
      
              // 2.3 给佳能相机一个变焦镜头进行加持
              Photographable nikonCameraWithZoomLens = new ZoomLens(nikonCamera);
              // 2.4 输出有了变焦镜头加持后的佳能相机的像素值
              System.out.println(String.format("变焦镜头加持后的尼康相机像素大小为:%s", nikonCameraWithZoomLens.getPixel()));
      
              // 2.5 在佳能相机有一个变焦镜头进行加持的基础上,在给上一个定焦镜头的加持
              Photographable nikonCameraWithZoomLensAndFixedFocusLens = new FixedFocusLens(nikonCameraWithZoomLens);
              // 2.6 在佳能相机有一个变焦镜头进行加持的基础上,在给上一个定焦镜头进行叠加
              System.out.println(String.format("变焦镜头和定焦镜头加持后的尼康相机像素大小为:%s", nikonCameraWithZoomLensAndFixedFocusLens.getPixel()));
          }
      }
      

  6. 源码展示

    • JDK中的字节流中的设计采用了装饰者模式。其中InputStream为Component角色,FileInputStream为具体的被装饰者。BufferedInputStream为具体的装饰者,其通过持有InputStream引用,来增强该对象的实现类(其中之一为FileInputStream)的read()方法。

      InputStream.java

      /**
       * Component角色
       */
      public abstract class InputStream implements Closeable {    
      }
      

      FileInputStream.java

      /**
       * 被装饰者:用于文件传输
       */
      public class FileInputStream extends InputStream {
      }
      

      FilterInputStream.java

      /**
       * Decorator角色
       */
      public class FilterInputStream extends InputStream {
          /**
           * The input stream to be filtered.
           */
          protected volatile InputStream in; 
          
          protected FilterInputStream(InputStream in) {
              this.in = in;
          }
      }
      

      BufferedInputStream.java

      /**
       * 装饰者:继承FilterInputStream,用于文件传输,增强为带缓冲的文件传输流
       */
      public class BufferedInputStream extends FilterInputStream {
          
          /**
           * 传入被装饰对象引用
           */
          public BufferedInputStream(InputStream in) {
              this(in, DEFAULT_BUFFER_SIZE);
          } 
          
          public BufferedInputStream(InputStream in, int size) {
              super(in);
              if (size <= 0) {
                  throw new IllegalArgumentException("Buffer size <= 0");
              }
              buf = new byte[size];
          } 
          
          /**
           * 对InputerStream的read()方法进行增强
           */
          public synchronized int read() throws IOException {
              if (pos >= count) {
                  fill();
                  if (pos >= count)
                      return -1;
              }
              return getBufIfOpen()[pos++] & 0xff;
          }
      }
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值