动态地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。

                                                ——《设计模式》GoF

作用:在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

比如,我们现在想设计一个日志类,记录DB日志(或文本日志),要求能够对日志的优先级 和 错误级别进行记录。
也就是对这个日志类添加了记录错误级别 和 优先级的功能。后续还可能增加其他的功能。

 
public interface Log {
public void write(String logContent);
}

public class DatabaseLog implements Log{

    @Override
public void write(String logContent) {
System.out.println("记录DB-Log:" + logContent);
} }
public class TextFileLog implements Log{

    @Override
public void write(String logContent) {
System.out.println("记录TextFile-Log:" + logContent);
} }

用于给日志类添加新功能的LogWrapper类:

public abstract class LogWrapper implements Log{
protected Log log; @Override
public void write(String logContent) {
log.write(logContent);
} }
public class LogErrorWrapper extends LogWrapper{
private String errorLevel; public LogErrorWrapper(Log log) {
super();
this.log = log;
} public String getErrorLevel() {
return errorLevel;
} public void setErrorLevel(String errorLevel) {
this.errorLevel = errorLevel;
} @Override
public void write(String logContent) {
logErrorLevel(errorLevel);
super.write(logContent);
} private void logErrorLevel(String errorLevel) {
System.out.println("错误级别:" + errorLevel);
} }
public class LogPriorityWrapper extends LogWrapper{
private String priority; public LogPriorityWrapper(Log log) {
super();
this.log = log;
} public String getPriority() {
return priority;
} public void setPriority(String priority) {
this.priority = priority;
} @Override
public void write(String logContent) {
logPriority(priority);
super.write(logContent);
} private void logPriority(String priority) {
System.out.println("优先级:" + priority);
} }

客户端调用:

public class Client {

    public static void main(String[] args) {
Log log = new DatabaseLog(); // DB-log
LogErrorWrapper errorWrapper = new LogErrorWrapper(log);// 1级错误级别 DB-log
LogPriorityWrapper priorityWrapper = new LogPriorityWrapper(errorWrapper); // 特别优先 1级错误级别 DB-log errorWrapper.setErrorLevel("1级错误");
priorityWrapper.setPriority("特别优先"); priorityWrapper.write("Hello World!");
}
}

输出结果:

优先级:特别优先
错误级别:1级错误
记录DB-Log:Hello World!

从上面的代码,我们可以看出,DatabaseLog类只拥有最简单的日志打印功能,而LogWrapper类实现了Log且持有Log的引用,而LogWrapper的子类对Log的功能进行了不同的扩展。而且这些扩展的功能对Log是完全透明的。

从调用处,我们可以看到,在LogWrapper(Decorator)子类的构造器中,我们除了传入Log的子类外,同样可以传入LogWrapper自己的子类,这样装饰的功能就能够进行叠加。这也是为什么我们让Decorator抽象类实现Log接口的原因。

因此,如果现在需要加一个功能,我们只需要添加一个功能的装饰子类就可以了,不需要添加其它的子类。它好就好在拥有运行时的灵活性,可以在需要用时随意组合功能,而不需要静态地把各种功能组合写死在代码中。

 

最新文章

  1. while用法一例
  2. IO(四)----对象的序列化
  3. svn做目录访问控制(AuthzSVNAccessFile)
  4. 团队开发——冲刺2.a
  5. C# 截取带路径的文件名字,扩展名,等等 的几种方法
  6. 全代码实现ios-3
  7. mkimage command not found
  8. 上下切换js
  9. HBase 简介(强烈推荐看)
  10. Webform用户控件
  11. Android源码编译常见错误(持续更新)
  12. 【Django】django 的request和response(转)
  13. poj2828(线段树查找序列第k小的值)
  14. 以太坊智能合约介绍,Solidity介绍
  15. Linux系统(X64)7 安装Oracle11g完整安装图文教程另附基本操作
  16. 自学之jQuery
  17. Docker在windows7上的安装
  18. PHP 传值操作和传地址操作
  19. Android -- AudioPlayer
  20. vue.js中请求数据v-for循环使用数据

热门文章

  1. HTTPS-HSTS协议(强制客户端使用HTTPS与服务器创建连接)
  2. 使用iostat分析IO性能
  3. JS页面间传值
  4. jquery得到iframe src属性值的方法
  5. 关于sphinx+PHP在高并发时响应性能低下的解决办法
  6. apache使用ssl数字证书
  7. 微信公众号开发笔记(C#)
  8. phpcms日期时间
  9. php 添加redis扩展(二)
  10. Jquery中的offset()和position()