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接口的原因。

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

 
posted on 2014-12-26 14:28  快鸟  阅读(411)  评论(0编辑  收藏  举报