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

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

     
  • 相关阅读:
    尝试了一下Flex
    Flash版的拉格朗日插值程序
    关于CSS属性display:none和visible:hidden的区别
    KMaster知识管理平台功能简介
    企业级知识库系统KMaster推荐
    ie6下的location.href错误
    利用Jquery实现http长连接(LongPoll)
    jQuery高亮插件
    当前知识管理系统的焦点问题以及我的一些解决办法
    知识库如何跟其他业务系统结合
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/4186717.html
Copyright © 2020-2023  润新知