装饰者模式


装饰者模式

1.基础知识

定义∶

在不改变原有对象的基础之上,将功能附加到对象上

提供了比继承更有弹性的替代方案(扩展原有对象功能)

类型∶结构型

通过构造方法,传入子类,包装子类,在装饰者类中用父类接收基类子类对象,返回父类对象,可以做到无限包装

适用场景

扩展一个类的功能或给一个类添加附加职责

动态的给一个对象添加功能,这些功能可以再动态的撤销

优点

继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能

通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果

符合开闭原则

缺点

会出现更多的代码,更多的类,增加程序复杂性

动态装饰时,多层装饰时会更复杂

相关设计模式

装饰者模式和代理模式

装饰者模式和适配器模式


2.实战

这里用奶茶举个栗子,单杯奶茶卖8块钱,椰果1份2块,布丁1份3块,我想要加2份椰果,1份布丁。

UML如图:

image-20220118165115364

/**
 * 奶茶装饰者类,类中组合奶茶抽象类
 */
public abstract class AbstractDecorator extends ATeaMilk {
    //继承一个抽象类,并装配这个抽象对象
    private ATeaMilk aTeaMilk;

    public AbstractDecorator(ATeaMilk aTeaMilk) {
        this.aTeaMilk = aTeaMilk;
    }

    protected abstract void doSomething();

    @Override
    protected String getDesc() {
        return this.aTeaMilk.getDesc();
    }

    @Override
    protected int cost() {
        return this.aTeaMilk.cost();
    }
}
/**
 * 奶茶基类
 * @Author LYS
 * @Date 2022/1/18 16:38
 * @Version 1.0
 */
public abstract class ATeaMilk {
    protected abstract String getDesc();
    protected abstract int cost();
}
/**
 * 椰果装饰类,1份2块钱
 *
 * @Author LYS
 * @Date 2022/1/18 16:41
 * @Version 1.0
 */
public class CoconutDecorator extends AbstractDecorator {
    public CoconutDecorator(ATeaMilk aTeaMilk) {
        super(aTeaMilk);
    }

    @Override
    protected void doSomething() {

    }

    @Override
    protected String getDesc() {
        return super.getDesc() + " 加一份椰果2块";
    }

    //一份椰果2块钱
    @Override
    protected int cost() {
        return super.cost() + 2;
    }
}
/**
 * 布丁类 一份布丁3块钱
 * @Author LYS
 * @Date 2022/1/18 16:44
 * @Version 1.0
 */
public class PuddingDecorator extends AbstractDecorator{
    public PuddingDecorator(ATeaMilk aTeaMilk) {
        super(aTeaMilk);
    }

    @Override
    protected void doSomething() {

    }
    @Override
    protected String getDesc() {
        return super.getDesc() + " 加一份布丁3块";
    }

    //一份布丁3块钱
    @Override
    protected int cost() {
        return super.cost() + 3;
    }
}
/**
 * @Author LYS
 * @Date 2022/1/18 16:40
 * @Version 1.0
 */
public class TeaMike extends ATeaMilk {
    @Override
    protected String getDesc() {
        return "奶茶8块";
    }

    //奶茶默认8块一杯
    @Override
    protected int cost() {
        return 8;
    }
}
public class Test {
    public static void main(String[] args) {
        //ATeaMilk是所有类的抽象类
        ATeaMilk aTeaMilk;
        //TeaMike是ATeaMilk的实现类 定义一杯普通奶茶 定义方法cost是8
        aTeaMilk = new TeaMike();
        //CoconutDecorator();传入ATeaMilk基类   的实现类 定义方法cost是super.cost()+2;也就是8+2 返回ATeaMilk对象
        aTeaMilk = new CoconutDecorator(aTeaMilk);
        aTeaMilk = new CoconutDecorator(aTeaMilk);
        //PuddingDecorator();传入ATeaMilk基类   的实现类 定义方法cost是super.cost()+3;也就是8+3 返回ATeaMilk对象
        aTeaMilk = new PuddingDecorator(aTeaMilk);
        //这里调用cost()方法,应为当前aTeaMilk已经包装了好几层。这个调用就是不断的入栈出栈调用的
        System.out.println(aTeaMilk.getDesc() + " 销售价格:" + aTeaMilk.cost());
    }
}

image-20220118165219405


3.源码

java io

增加缓存类有很多

BufferedReader类继承Reader 组合reader 就是一个装饰者类,可以无限的装饰继承reader的子类类似实战中的奶茶类

public class BufferedReader extends Reader {

    private Reader in;
    
    public BufferedReader(Reader in, int sz) {
        super(in);
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        this.in = in;
        cb = new char[sz];
        nextChar = nChars = 0;
    }

FilterInputStream 继承InputStream ,类里又组装了InputStream in

class FilterInputStream extends InputStream {
    /**
     * The input stream to be filtered.
     */
    protected volatile InputStream in;

spring中TransactionAwareCacheDecorator处理缓存和同步事务 这个类就是Cache的装饰者类

public class TransactionAwareCacheDecorator implements Cache {

   private final Cache targetCache;
   public TransactionAwareCacheDecorator(Cache targetCache) {
       Assert.notNull(targetCache, "Target Cache must not be null");
       this.targetCache = targetCache;
   }

wrapper结尾要么是装饰者模式要么是适配器模式,看具体的类的继承实现结构

image-20220118171646171

mybatis中

image-20220118171814738

相关