在设计像类这样的记录器时处理条件语句?

时间:2016-09-09 14:35:18

标签: java oop design-patterns

在设计像log4j这样的类时,如何处理条件语句?

以log4j为例,一个类可以有不同的级别(信息,警告,错误,其他......)。现在要打印不同级别,每个级别需要不同的方法。所以可以有如下基本设计:

public class CustomLogger {

    enum Level{
        INFO, WARNING, ERROR;
    }

    private Level level;

    public CustomLogger(Level level) {
        this.level = level;
    }

    public void info(String s){
        if(level == Level.INFO || level == Level.WARNING || level == Level.ERROR){
            System.out.println(s);
        }
    }

    public void warning(String s){
        if(level == Level.WARNING || level == Level.ERROR){
            System.out.println(s);
        }
    }

    public void error(String s){
        if(level == Level.ERROR){
            System.out.println(s);
        }
    }
}

我猜这个设计的问题是它有太多的条件,如果我需要添加一个新状态,我将不得不修改所有if情况。所以我认为可能是更好的设计如下:

有一个State超类,它由类Info,类Warning和类Error扩展。 State类包含方法printInfo()printWarning()printError()。所有子类都实现这些方法,并在需要时留空。作为示例,类Warning看起来像:

class Warning extends State{

    public void printInfo(String s){
        //don't print
    }

    public void printWarning(String s){
        System.out.println(s);
    }

    public void printError(String s){
        System.out.println(s);
    }
}

现在CustomLogger将与State建立关联,并在某个时刻注入CustomLoggerState中的所有方法都会调用public class CustomLogger { private State state; public CustomLogger(State state) { this.state = state; } public void info(String s){ state.printInfo(s); } public void warning(String s){ state.printWarning(s); } public void error(String s){ state.printError(s); } } 类实现的方法。类似的东西:

State

尽管这消除了条件情况,但它引起了方法调用的依赖性。如果我添加一个新的printState()那么状态$方法必须添加到每个子类,我想这不是一个好习惯。在这种情况下还能做些什么?

1 个答案:

答案 0 :(得分:1)

在这种情况下,最佳答案取决于系统的要求将来如何变化。即使您遵循Open/close principle,也无法阻止违反此原则的所有可能情况,因此您尝试在设计中覆盖您认为更有可能出现的情况。

无论如何,您的案例研究的一个很好的解决方案类似于Java Logger实现的解决方案。数值与Logger级别相关联(每个可能的Level都有其值),允许您检查当前Logger是否应该使用单个{{if向日志写入任何内容1}}。此外,在不修改当前代码的情况下扩展其行为非常容易。

例如,当您致电Logger#info(String)时:

public void info(String msg) {
    log(Level.INFO, msg);
}

方法log如下:

public void log(Level level, String msg) {
    if (!isLoggable(level)) {
        return;
    }
    // do any logging you want here
}

最后是关键isLoggable

public boolean isLoggable(Level level) {
    if (level.intValue() < levelValue || levelValue == offValue) {
        return false;
    }
    return true;
}

其中levelValueLogger的“当前有效等级值”。