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