装饰者设计模式
-
简单介绍
装饰者模式是一种结构型设计模式。该模式能够动态的将新的功能附加(装饰)在某个类(被装饰者)的方法中。该模式能够很好的满足OCP原则。
-
使用场景
项目开发过程中,需要对某个类的方法在已有功能的基础上进行一个增强。并且不希望该类原有代码进行修改。
-
场景举例
JDK中有许多针对字节流传输的类(InputStream的子类),如:FileInputStream类等,该类是一个不带缓冲区的类,效率并不高。设计者为此引入了BufferedInputStream,持有FileInputStream对象,并引入缓冲区,来提高传输效率,从而达到一个增强的作用。其中FileInputStream是被装饰类,BufferedInputStream是装饰类。
-
UML类图
-
具体实现
-
描述
-
被装饰者为相机类:佳能相机(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())); } }
-
-
源码展示
-
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; } }
-