1,定义
动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。
2,代码实现
例如现在有这样一个需求,需要将日志打印成统一封装的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() {
//拼装了一些运行时信息
}
}
3,与代理模式的区别
这里很容易看出,代码结构和代理模式的结构非常相似,那么和代理模式的区别在哪里呢?
1,首先代理模式相对装饰模式在客户端不是透明的,用户不知道代理委托了另外一个对象,而装的饰模式则是客户指定了需要装饰的类
2,代理模式重在控制,控制对目标对象的访问,对于用户来说是被动的,而装饰模式则是添加一些额外的功能,重在装饰方法,对于用户来说是主动的。
3,实用场景:如果你写了一个方法,后面想给它另外添加一些额外的功能,你可以选择用装饰模式
如果你写了一堆方法,后面想统一给这些方法增加一些功能,你可以用代理模式,例如spring aop 添加事务和日志就是个典型的代理模式的实现。