2017-01-26 4 views
10

私はいくつかのフレームワークで作業していますが、抽象クラスが実装されています。抽象クラスでのオプションの実装

これで、ユーザーが設定できる必要がある他のものがありましたが、これはオプションです。

ので、代わりの抽象メソッド:私はちょうどインタフェースの実装をチェックする考え

public abstract class AbstractModule { 
    public void doSomething() { 
     if (logMessage() != null) 
      System.out.println(logMessage()); 
     doStuff(); 
    } 

    protected abstract String logMessage(); // I'm optional 
    protected abstract void doStuff(); 
} 

public interface Log { 
    String logMessage(); 
} 

public abstract class AbstractModule { 
    public void doSomething() { 
     if (this instanceof Log) { 
      if (((Log) this).logMessage() != null) 
       System.out.println(((Log) this).logMessage()); 
     } 
     doStuff(); 
    } 

    protected abstract void doStuff(); 
} 

だから、誰かがインターフェイスでAbstractModuleを実装している場合、それはまた、表示されるでしょうログインメッセージ。私が見ている実装者のメリット:最初の例のように、logMessage()の実装には注意する必要はありません。これは有効なアプローチですか、それとも別の方法で行うべきですか?

ありがとうございます! instanceofに手を伸ばす

よろしく

答えて

4

私はロガーあなたのモジュールのコンポーネントを作成し、抽象クラスでデフォルトノーオペレーションロガーを定義します。この方法でinstanceofを取り除いても、柔軟性は維持されます。ここで

interface Log { 
    void logMessage(); 
} 

public abstract class AbstractModule { 
    protected Log log; 

    public AbstractModule(){ 
     this.log =() -> {}; 
    } 

    public AbstractModule(Log log){ 
     this.log = log; 
    } 

    public void doSomething() {   
     log.logMessage();   
     doStuff(); 
    } 

    protected abstract void doStuff(); 
} 

AbstractModuleを拡張する例のクラスである:

public class Module extends AbstractModule{ 

    public Module(){ 
     super(() -> System.out.println("message"));   
    } 

    @Override 
    protected void doStuff() { 
     // do stuff  
    } 

} 

あなたはロガーを公開したい場合は、抽象クラスでロガーのゲッターメソッドを定義することができます

public Log getLogger(){ 
    return log; 
} 
2

コードのにおいのビットです。通常はそれを行うより良い方法があります。

私の最初の本能は、基本クラスの無操作方法持つことです。

class AbstractModule { 
    final void doSomething() { 
    maybeLogMessage(); 
    } 

    void maybeLogMessage() {} 
} 

明らかに何もしません。サブクラスでオーバーライドすることができます:

class Subclass extends AbstractModule { 
    @Override void maybeLogMessage() { 
    System.out.println("The message"); 
    } 
} 

メッセージを出力します。

すべてのサブクラスでSystem.out.printlnを繰り返す必要がない場合は、メソッドから特別な値を戻して、ログに記録しないことを示すことができます。たとえば、非空に文字列を要求することができます。

class AbstractModule { 
    final void doSomething() { 
    String message = logMessage(); 
    if (!message.isEmpty()) { System.out.println(message); } 
    } 

    String logMessage() { return ""; } 
} 

class Subclass extends AbstractModule { 
    @Override String logMessage() { 
    return "The message"; 
    } 
} 
4

この質問はjava-8とタグ付けされているので、別の解決方法はinterfacedefaultの方法を使用することです。

public interface Module { 
    public default void doSomething() { 
     if (logMessage() != null) 
      System.out.println(logMessage()); 
     doStuff(); 
    } 

    public default String logMessage() { return null; } // I'm optional 
    public void doStuff(); 
} 

使用法:抽象クラスの代わりにこのアプローチを使用しての

class NoLogModule implements Module { 
    @Override 
    public void doStuff() { } 
} 

class LogModule implements Module { 

    @Override 
    public void doStuff() { } 

    @Override 
    public String logMessage() { return "Message "; } 

} 

一つの利点は、あなたのクラスは今、別のクラスから拡張して自由であるということです。このアプローチの1つの短所は、からdoSomethingメソッドを無効にすることができないことです(コードに基づいて、これは気にしないように見えます)

関連する問題