设计模式-装饰器

定义:
结构型装饰器模式(Decorator Pattern || Wrapper Pattern )指在不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的替代方案,生活中常见的例子:类似煎饼,水果蛋糕...

适用场景:
1.用于扩展一个类的功能或给一个类附加职责。
2.动态的给一个对象添加功能,这些功能可以再动态的撤销。
优点:
1.装饰器属于继承的有力补充,比继承灵活,不改变原有对象的情况下动态的给对象扩展功能,增加即用。
2.通过使用不同装饰器类以及这些类的排序组合,可实现不同效果。
3.完全遵守开闭原则。
缺点:
1.会出现更多的代码与类,增加了程序复杂度
2.动态装饰时会更复杂

示例:

/**
 * 抽象组件,以煎饼为例
 */
public abstract class Battercake {
    protected abstract String getMsg();
    protected abstract BigDecimal getPrice();
}
/**
 * 一个正常的煎饼,不加任何辅材
 */
public class BaseBattercake extends Battercake {
    public String getMsg(){ return "煎饼"; }
    public BigDecimal getPrice(){
        return new BigDecimal(5);
    }
}
/**
 * 装饰器,继承煎饼抽象
 */
public class BattercakeDecorator extends Battercake{
    private Battercake battercake;
    /**
     * 装饰器最大特征:
     * 构造方法必须,也就是说子类必须实现一个带参数的构造方法
     * 并且参数一定是抽象组件
     */
    BattercakeDecorator(Battercake battercake){
        this.battercake = battercake;
    }
    protected String getMsg(){
        return this.battercake.getMsg();
    }
    protected BigDecimal getPrice(){
        return this.battercake.getPrice();
    }
}
/**
 * 需要在煎饼上加鸡蛋,衍生出第二个装饰器
 */
public class EggDecorator extends BattercakeDecorator{
    /**
     * 构造器调用父类
     */
    EggDecorator(Battercake battercake){
        super(battercake);
    }
    protected String getMsg(){
        // 增加辅材
        return super.getMsg() + ",一个鸡蛋";
    }
    protected BigDecimal getPrice(){
        return super.getPrice().add(new BigDecimal(1));
    }
}
/**
 * 需要在煎饼上加香肠,衍生出第三个装饰器,以此类推。
 */
public class SauageDecorator extends BattercakeDecorator{
    /**
     * 构造器调用父类
     */
    SauageDecorator(Battercake battercake){
        super(battercake);
    }
    protected String getMsg(){
        // 增加辅材
        return super.getMsg() + ",一根香肠";
    }
    protected BigDecimal getPrice(){
        return super.getPrice().add(new BigDecimal(2));
    }
}
// 模拟客户端
public class MainExcute {
    // 当前log输出是字符串,可将log封装成装饰器,输出json格式。
    private final static Logger logger = Logger.getLogger(MainExcute.class);
    public static void main(String[] args) {
        /**
         * 使用时可以透明动态的扩展,需要什么就创建不同的装饰器
         */
        Battercake battercake = new BaseBattercake();
        logger.info(battercake.getMsg()+":总价"+battercake.getPrice()+"元");
        battercake = new EggDecorator(battercake);
        battercake = new EggDecorator(battercake);
        logger.info(battercake.getMsg()+":总价"+battercake.getPrice()+"元");
        battercake = new SauageDecorator(battercake);
        logger.info(battercake.getMsg()+":总价"+battercake.getPrice()+"元");
        /**
         * 装饰器在源码中的应用
         * io流中也用的比较多,例:InputStream -> FileInputStream —> BufferedInputStream
         */
    }
}

类图:

image.png

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容