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"}