首页 > 代码库 > Decorator装饰模式

Decorator装饰模式

动态地给一个对象增加一些额外的职责。就增加功能而言,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接口的原因。

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

 

Decorator装饰模式