【问题标题】:Handling conditional statements while designing a logger like class?在设计类记录器时处理条件语句?
【发布时间】:2016-09-10 11:45:32
【问题描述】:

在设计像 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 条件,如果我需要添加一个新的状态,我必须修改所有的 if 情况。所以我认为可能更好的设计如下:

有一个State 超类,它由InfoWarningError 类扩展。 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 建立关联,该关联将在某个时刻注入其中,CustomLogger 中的所有方法将调用State 类实现的方法。比如:

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() 方法必须添加到每个子类中,我认为这不是一个好习惯。在这种情况下还能做什么?

【问题讨论】:

  • 我真的认为你需要 Replace Conditional with Polymorphism 重构
  • @ArnavBorborah 我研究了它,但想不出在这种情况下如何让它发挥作用。如果所有州都独立工作,我可以使用它,但在这里它们是相关的。如果水平在Info,我需要允许WarningError等等。
  • 如果我没记错的话,log4j 有一种方法可以接收级别和消息log(Level, String),因此所需级别与设置级别的检查都在一个地方。然后像info(String) 这样的方法是调用另一个方法的语法糖。

标签: java oop design-patterns


【解决方案1】:

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

无论如何,一个很好的案例研究解决方案类似于 Java Logger 实现的解决方案。其中一个数值与Logger 级别相关联(每个可能的Level 都有其值),这允许您检查当前Logger 是否应该使用单个if 将任何内容写入日志。此外,无需修改当前代码即可轻松扩展其行为。

例如当你打电话给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 的“当前有效电平值”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    • 2022-06-10
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    相关资源
    最近更新 更多