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 \n价格:%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"}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值