2016-09-09 8 views
0

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); 
     } 
    } 
} 

私は推測するこの設計の問題は、それは私がすべて変更しなければならない新しい状態を追加する必要がある条件ならば、ケースにはあまりにも多くを持っていることである次のように基本的な設計があるかもしれませんケースの場合。だから私が何を考えて可能性があり、次のように優れたデザインです。

がクラスInfo、クラスWarningとクラスErrorによって拡張されStateスーパークラスがあります。 StateクラスはメソッドprintInfo(),printWarning()およびprintError()を持っています。すべてのサブクラスはこれらのメソッドを実装し、必要なときは空白のままにします。

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は、いくつかの時点でそれに注入され、CustomLoggerのすべてのメソッドは、Stateクラス実装のメソッドを呼び出しますStateとの関連を持つことになります。一例として、クラスWarningは次のようになります。次のようなものがあります。

条件付きのケースは削除されますが、メソッド呼び出しの依存関係が発生します。私が新しいStateを追加した場合、その状態printState()はすべてのサブクラスに追加する必要があります。これは私が推測することは良い方法ではありません。そのような場合には他に何ができますか?

+0

私は本当にあなたが[多型を条件に置き換える](http://refactoring.com/catalog/replaceConditionalWithPolymorphism)が必要だと思います。html)refactoring –

+0

@ArnavBorborah私はそれを調べましたが、このケースでどのように動作させることができるのか考えられませんでした。すべての州が独立して仕事をするなら、私はそれを使うことができましたが、ここでは関連しています。 'Info'のレベルであれば、' Warning'や 'Error'などを許可する必要があります。 – rd22

+0

正しくリコールすれば、log4jにはレベルとメッセージ(log(Level、String))を受け取るメソッドがありますので、必要なレベルのチェックと設定レベルのチェックがすべて1か所にあります。それで 'info(String)'のようなメソッドは、他のメソッドを呼び出す構文的な砂糖です。 –

答えて

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

levelValueは「現在ある
public boolean isLoggable(Level level) { 
    if (level.intValue() < levelValue || levelValue == offValue) { 
     return false; 
    } 
    return true; 
} 

012の有効レベル値。

関連する問題