• java设计模式(七)——装饰器模式


    1、基本概念

    装饰器模式( Decorator Pattern ) ,也称为包装模式( Wrapper Pattern )是指在不改变原有对象
    的基础之上,将功能附加到对象上,扩展原有对象的功能), 属于结构型模式。


    我们常用的各种io流就是一种装饰器模式,mybatis的catch也是。

    生活中案例有很多如:煎饼果子,蛋糕,麻辣烫等

    2、类图和角色

    主要有角色:

    抽象组件或接口:规定被装饰者的原有属性和行为

    具体组件/基本组件/被装饰者:拥有最基本的属性和行为

    抽象装饰器:规定装饰具体组件的属性和行为(看业务可不需要)

    具体装饰器:扩展被装饰者的功能

    3、案例

    案例:蛋糕:蛋糕没有加任何东西的时候,价格是50,加了巧克力是+20,加了草莓是+30

    类图:

     接口ICake:

    public  interface ICake {
    
        String getName();
    
        Integer getPrice();
    }

    被装饰者BaseCake:

    public class BaseCake implements ICake {
    
        @Override
        public String getName() {
            return "蛋糕";
    
        }
    
        @Override
        public Integer getPrice() {
            return 50;
        }
    }

    具体装饰者1:ChocolateCakeDecorator 

    public class ChocolateCakeDecorator implements ICake {
    
        public ICake iCake;
    
        public ChocolateCakeDecorator(ICake iCake) {
            this.iCake = iCake;
        }
    
        @Override
        public String getName() {
            return (iCake.getName()+"+巧克力");
        }
    
        @Override
        public Integer getPrice() {
           return  (iCake.getPrice()+20);
        }
    }

    具体装饰者2:StrawberryCakeDecorator 

    public class StrawberryCakeDecorator implements ICake {
    
    
        public ICake iCake;
    
        public StrawberryCakeDecorator(ICake iCake) {
            this.iCake = iCake;
        }
    
    
        @Override
        public String getName() {
            return iCake.getName()+"+草莓";
        }
    
        @Override
        public Integer getPrice() {
            return iCake.getPrice()+30;
        }
    }

    测试:

    public class Test {
        public static void main(String[] args) {
    
            ICake iCake;
    
            iCake = new BaseCake();
    
            iCake = new ChocolateCakeDecorator(iCake);
    
            iCake = new StrawberryCakeDecorator(iCake);
    
            System.out.printf("蛋糕: %s 
    价格:%d", iCake.getName(), iCake.getPrice());
        }
    }

    输出:

    蛋糕: 蛋糕+加巧克力+草莓 
    价格:100

    这里我们没有用到抽象的装饰器,如果加上抽象的装饰器

     抽象的装饰器:AbstractCakeDecorator 

    public abstract class AbstractCakeDecorator implements ICake {
    
        public ICake iCake;
    
        public AbstractCakeDecorator(ICake iCake) {
            this.iCake = iCake;
        }
    
        public abstract void doOtherthing();
    
        @Override
        public String getName() {
            return this.iCake.getName();
        }
    
        @Override
        public Integer getPrice() {
            return this.iCake.getPrice();
        }
    
    }

    具体装饰器1:ChocolateCakeDecorator 

    public class ChocolateCakeDecorator extends AbstractCakeDecorator {
    
    
        public ChocolateCakeDecorator(ICake iCake) {
            super(iCake);
        }
    
        @Override
        public void doOtherthing() {
    
        }
    
        @Override
        public String getName() {
            return (super.getName()+"+巧克力");
        }
    
        @Override
        public Integer getPrice() {
           return  (super.getPrice()+20);
        }
    }

    具体装饰器2:StrawberryCakeDecorator 

    public class StrawberryCakeDecorator extends AbstractCakeDecorator {
    
    
        public StrawberryCakeDecorator(ICake iCake) {
            super(iCake);
        }
    
        @Override
        public void doOtherthing() {
    
        }
    
        @Override
        public String getName() {
            return super.getName()+"+草莓";
        }
    
        @Override
        public Integer getPrice() {
            return super.getPrice()+30;
        }
    }

    其他都不变

    4、优缺点

    优点:

    1、可以动态的扩展一个对象的功能

    2、完全是遵循开闭原则,当需要扩展功能的时候,只需要加上一个装饰器即可

    例如我们有这样的一个需求:

    public class Test {
    
        private static Logger logger = LoggerFactory.getLogger(Test.class);
    
        public static void main(String[] args) {
            logger = new JsonLoggerDecorator(logger);
            logger.info("hhh");
        }
    }

    我们的日志打印是这样的:

    [main] INFO com.springboot.designPattern.decorator.ex.Test - 哈哈哈

     我们希望将日志信息转为json字符串,存入mongodb中,进行日志信息的处理

    [main] INFO com.springboot.designPattern.decorator.ex.Test - {"date":"2020-07-07T16:05:14.292","message":"哈哈哈","class":"com.springboot.designPattern.decorator.ex.Test"}

    那么就可以用到装饰器模式

    导包:

    <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.56</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>2.12.1</version>
            </dependency>

    写个抽象的装饰器AbstractLoggerDecorator 实现Logger接口:

    public abstract class AbstractLoggerDecorator implements Logger{
    
        public Logger logger;
    
        public AbstractLoggerDecorator(Logger logger){
            this.logger = logger;
        }
    
        @Override
        public String getName() {
            return null;
        }
    
        @Override
        public boolean isTraceEnabled() {
            return false;
        }
    
        @Override
        public void trace(String msg) {
    
        }
    
        @Override
        public void trace(String format, Object arg) {
    
        }
    
        @Override
        public void trace(String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void trace(String format, Object... arguments) {
    
        }
    
        @Override
        public void trace(String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isTraceEnabled(Marker marker) {
            return false;
        }
    
        @Override
        public void trace(Marker marker, String msg) {
    
        }
    
        @Override
        public void trace(Marker marker, String format, Object arg) {
    
        }
    
        @Override
        public void trace(Marker marker, String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void trace(Marker marker, String format, Object... argArray) {
    
        }
    
        @Override
        public void trace(Marker marker, String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isDebugEnabled() {
            return false;
        }
    
        @Override
        public void debug(String msg) {
    
        }
    
        @Override
        public void debug(String format, Object arg) {
    
        }
    
        @Override
        public void debug(String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void debug(String format, Object... arguments) {
    
        }
    
        @Override
        public void debug(String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isDebugEnabled(Marker marker) {
            return false;
        }
    
        @Override
        public void debug(Marker marker, String msg) {
    
        }
    
        @Override
        public void debug(Marker marker, String format, Object arg) {
    
        }
    
        @Override
        public void debug(Marker marker, String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void debug(Marker marker, String format, Object... arguments) {
    
        }
    
        @Override
        public void debug(Marker marker, String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isInfoEnabled() {
            return false;
        }
    
        @Override
        public void info(String msg) {
    
        }
    
        @Override
        public void info(String format, Object arg) {
    
        }
    
        @Override
        public void info(String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void info(String format, Object... arguments) {
    
        }
    
        @Override
        public void info(String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isInfoEnabled(Marker marker) {
            return false;
        }
    
        @Override
        public void info(Marker marker, String msg) {
    
        }
    
        @Override
        public void info(Marker marker, String format, Object arg) {
    
        }
    
        @Override
        public void info(Marker marker, String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void info(Marker marker, String format, Object... arguments) {
    
        }
    
        @Override
        public void info(Marker marker, String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isWarnEnabled() {
            return false;
        }
    
        @Override
        public void warn(String msg) {
    
        }
    
        @Override
        public void warn(String format, Object arg) {
    
        }
    
        @Override
        public void warn(String format, Object... arguments) {
    
        }
    
        @Override
        public void warn(String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void warn(String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isWarnEnabled(Marker marker) {
            return false;
        }
    
        @Override
        public void warn(Marker marker, String msg) {
    
        }
    
        @Override
        public void warn(Marker marker, String format, Object arg) {
    
        }
    
        @Override
        public void warn(Marker marker, String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void warn(Marker marker, String format, Object... arguments) {
    
        }
    
        @Override
        public void warn(Marker marker, String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isErrorEnabled() {
            return false;
        }
    
        @Override
        public void error(String msg) {
    
        }
    
        @Override
        public void error(String format, Object arg) {
    
        }
    
        @Override
        public void error(String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void error(String format, Object... arguments) {
    
        }
    
        @Override
        public void error(String msg, Throwable t) {
    
        }
    
        @Override
        public boolean isErrorEnabled(Marker marker) {
            return false;
        }
    
        @Override
        public void error(Marker marker, String msg) {
    
        }
    
        @Override
        public void error(Marker marker, String format, Object arg) {
    
        }
    
        @Override
        public void error(Marker marker, String format, Object arg1, Object arg2) {
    
        }
    
        @Override
        public void error(Marker marker, String format, Object... arguments) {
    
        }
    
        @Override
        public void error(Marker marker, String msg, Throwable t) {
    
        }
    }

    具体装饰器:JsonLoggerDecorator 

    public class JsonLoggerDecorator extends AbstractLoggerDecorator {
    
        public JsonLoggerDecorator(Logger logger) {
            super(logger);
        }
    
    
        @Override
        public void info(String msg) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("message",msg);
            jsonObject.put("class",logger.getName());
            jsonObject.put("date", LocalDateTime.now());
            logger.info(jsonObject.toString());
        }
    
    }

    测试:

    public class Test {
    
        private static Logger logger = LoggerFactory.getLogger(Test.class);
    
        public static void main(String[] args) {
            logger = new JsonLoggerDecorator(logger);
            logger.info("哈哈哈");
        }
    }

    打印结果:

    [main] INFO com.springboot.designPattern.decorator.ex.Test - {"date":"2020-07-07T16:05:14.292","message":"哈哈哈","class":"com.springboot.designPattern.decorator.ex.Test"}
  • 相关阅读:
    git/github轻松上传本地项目
    ubuntu下python+flask+mysql完整开发环境配置
    木马另类删除文件的方法
    OpenCV资源
    实现bmp文件到png文件转换
    通过进程ID获得该进程主窗口的句柄
    有趣的Lua表
    让程序在win7下运行时弹出"以管理员身份运行"
    LuaStudio源码分析2资源文件
    LuaCURL
  • 原文地址:https://www.cnblogs.com/tdyang/p/13260896.html
Copyright © 2020-2023  润新知