装饰器模式,coding过程中的常用模式

111 阅读3分钟

在日常的编码过程,你已经有意无意的在使用各种设计模式,只是你没有意识到而已,今天讲解一种非常实用的设计模式-装饰器模式

  • 定义 装饰者模式在不改变原有对象的基础上,通过组合的方式给对象增加新功能

  • 优点

  1. 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能
  2. 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
  3. 符合开闭原则
  • 缺陷
  1. 会出现更多的代码,更多的类,增加程序复杂性
  2. 动态装饰时,多层装饰时会更复杂

也正是这些缺陷给我们学习有些装饰器写的源码带来了困难,千里之行,始于足下,冰冻三尺非一日之寒,学习每一种设计模式一定是循序渐进,从最基本的例子开始掌握再到实践应用

  • 组成部分 Component(组件) :组件接口或抽象类定义了全部组件实现类以及所有装饰器实现的行为。

ConcreteComponent(具体组件实现类) :具体组件实现类实现了Component接口或抽象类。通常情况下,具体组件实现类就是被装饰器装饰的原始对象,该类提供了Component接口中定义的最基本的功能,其他高级功能或后序添加的新功能,都是通过装饰器的方式添加到该类的对象之上的

Decorator(抽象装饰器)所有装饰器的父类,它是一个实现了Component接口的类,并在其中封装了一个Component对象,也就是被装饰的对象。而这个被装饰的对象只要是Component类型即可,这就实现了装饰器的组合和复用

ConcreteDecorator(具体的装饰器) :该实现类要向被装饰对象添加某些功能

  • 基本demo
组件
public abstract class AbstractBattercake {

    protected abstract String getDesc();
    protected abstract int cost();
}
组件的具体实现类
public class Battercake extends AbstractBattercake {

    protected String getDesc() {
        return "煎饼";
    }

    protected int cost() {
        return 8;
    }
}
装饰器类
public abstract class AbstractDecorator extends AbstractBattercake {
    //所有装饰器的父类,它是一个实现了Component接口的类,并在其中封装了一个Component对象,也就是被装饰的对象
    private AbstractBattercake aBstractBattercake;

    public AbstractDecorator(AbstractBattercake aBstractBattercake) {
        this.aBstractBattercake = aBstractBattercake;
    }

    protected String getDesc() {
        return this.aBstractBattercake.getDesc();
    }

    protected int cost() {
        return this.aBstractBattercake.cost();
    }
}
具体的装饰器实现类
public class EggDecorator extends AbstractDecorator {

    public EggDecorator(AbstractBattercake aBstractBattercake) {
        super(aBstractBattercake);
    }

    @Override
    protected String getDesc() {
        return super.getDesc() + " 加一个鸡蛋";
    }

    @Override
    protected int cost() {
        return super.cost() + 1;
    }
}
具体的装饰器实现类
public class SausageDecorator extends AbstractDecorator {

    public SausageDecorator(AbstractBattercake aBstractBattercake) {
        super(aBstractBattercake);
    }

    @Override
    protected String getDesc() {
        return super.getDesc() + " 加一根香肠";
    }

    @Override
    protected int cost() {
        return super.cost() + 2;
    }
}
测试代码
public class DecoratorTest {
    public static void main(String[] args) {
        AbstractBattercake aBstractBattercake = new Battercake();
        aBstractBattercake = new EggDecorator(aBstractBattercake);
        aBstractBattercake = new SausageDecorator(aBstractBattercake);
        // 煎饼 加一个鸡蛋 加一根香肠 销售价格为: 11
        System.out.println(aBstractBattercake.getDesc() + " 销售价格为: " + aBstractBattercake.cost());
    }
}
  • UML类图

image.png

  • 实战应用:JSON打印日志
public class DecoratorLogger implements Logger {
    public Logger logger;    public DecoratorLogger(Logger logger) {        this.logger = logger;    }    
    @Override
    public void error(String str) {}

    @Override
    public void info(String str) {}
        
    //省略其他默认实现
}
public class JsonLogger extends DecoratorLogger {
public JsonLogger(Logger logger) {
        
        super(logger);
    }
        
    @Override
    public void info(String msg) {

        JSONObject result = composeBasicJsonResult();
        result.put("MESSAGE", msg);
        logger.info(result.toString());
    }
    
    @Override
    public void error(String msg) {
        
        JSONObject result = composeBasicJsonResult();
        result.put("MESSAGE", msg);
        logger.error(result.toString());
    }
    
    public void error(Exception e) {

        JSONObject result = composeBasicJsonResult();
        result.put("EXCEPTION", e.getClass().getName());
        String exceptionStackTrace = ExceptionUtils.getStackTrace(e);    
        result.put("STACKTRACE", exceptionStackTrace);
        logger.error(result.toString());
    }
    
    public static class JsonLoggerFactory {
        
        @SuppressWarnings("rawtypes")
        public static JsonLogger getLogger(Class clazz) {

            Logger logger = LoggerFactory.getLogger(clazz);
            return new JsonLogger(logger);
        }
    }
    
    private JSONObject composeBasicJsonResult() {
        //拼装了一些运行时信息
    }
}