22

空の NO-OP 実装を使用してインターフェイスのすべてまたは一部のメソッドを実装する、抽象的でない既定の実装が提供されるシナリオを説明する特定の設計パターンはありますか。これは、サブクラス自体が必要/使用しない可能性のあるメソッドを実装する負担をサブクラスに軽減することを目的として行われています。

public interface MyInterface {
    public void doThis();
    public void doThat();
    public void done();
}

public class MyClass implements MyInterface {
    public void doThis() {
        // NO-OP
    }
    public void doThat() {
        // NO-OP
    }
    public void done() {
        // Some standard implementation
    }
}

public class MuSubClass extends MyClass {
    public void doThat() {
        // Subclass only cares about doThat()
    }
}

SAX フレームワークの Java の DefaultHandlerMouseAdapterなど、このパターンが何度も使用されているのを見てきました。場合によっては、そのようなクラスはアダプターと呼ばれますが、アダプター パターンは 2 つの異なるインターフェイス間で変換されるという印象を受けました。

これらのインスタンスでは、そのインターフェイスの未定義のサブセットに変換されている宣言されたインターフェイスが 1 つしかないことを考えると、これがアダプター パターンの精神にどのように含まれているかは明確ではありません。

さらに、いくつかのメソッドが実装を持つ可能性があり、NullObject は伝統的にシングルトンであることを考えると、これがNullObject パターンにどのように準拠しているかはよくわかりません。

4

9 に答える 9

5

デフォルト実装の設計パターンはありません。

DoNothing私は通常、クラスの名前に接頭辞を追加します。その意図に応じて、BaseまたはDefault(後者は広く使用されています) も使用します。おそらくMouseAdapterと呼ばれるべきDefaultMouseListenerです。

気になる場合は、単純なDynamicProxyを使用して体系的にインターフェースをスタブすることができます。「適切な」デフォルト値 (オブジェクトの場合は null、数値の場合は 0 など) のみを返す必要があります。

ところで、これはとても良い質問です。

編集

さらに、これはスタブでもモックでもありません。スタブと混同される可能性がありますが、意図は異なります。

于 2009-08-11T11:06:08.307 に答える
2

この設計が春に使用されているのを見たことがあります。ここでは、FlowExecutionListenerAdapterという名前のクラスがあり、すべての FlowExecutionListener 操作の実装を節約できます。

ただし、Null Object パターンのようにも聞こえます。ただし、必要なビットのみを実装できるようにすることでインターフェイスの動作を変更するため、純粋にアダプターの世界の方が適していると思いますが、それは難しいものです。

この質問は以前に尋ねられたと確信していますか?

これは似ていますね?読む価値があるかもしれません。

于 2009-08-11T10:42:02.143 に答える
2

Swing (WindowListener を実装する WindowAdapter) でも使用されます。これは便利なアダプターにすぎません。この方法で 1 ~ 2 つのメソッドを定義するだけで、便利な windowlistener を使用できます。これは確かに Adapter パターンのインスタンスであり、抽象クラスの力も示しています。複数の実装の継承が役立つ場合がある理由を説明するための例でもあります。

通常のデザイン パターンと同様に、Temlate メソッドではフック操作を定義できます。これはオーバーライドされる可能性があります (抽象メソッドとは異なり、オーバーライドする必要があります) が、デフォルトの動作 (通常は NO-OP) も意味があります。

于 2009-08-11T12:18:06.443 に答える
1

素晴らしい質問です。

NoOpこのパターンのクラス名プレフィックスとして使い始めました。短く、明確で、オーバーロードされていません ( Empty[何も含まない?]、Null[Null オブジェクト パターン、どちらが異なる?]、Abstract[何らかの実装を提供しますか?]、[何らかの実装Baseを提供しますか?] など)。

複雑な操作中にインストルメンテーション用の「フック」を提供するサードパーティ API がある場合、このスタイルのクラスを作成することがあります。ライブラリによって提供される次の 2 つのクラスを検討してください。

public class LongRunningActionRunner {
    public void runSomethingLong(DecisionListener cdh) {
        // ...
    }
}

public interface DecisionListener {
    public void beforeFooHook();
    public void afterFooHook();
    public void beforeBarHook();
    public void afterBarHook();
    public void beforeBazHook();
    public void afterBazHook();
}

この場合、次のようなパターンを使用してクラスを正しくすることができます。

public class NoOpDecisionListener implements DecisionListener {
    @Override public Something beforeFooHook() {}
    @Override public Something afterFooHook() {}
    @Override public Something beforeBarHook() {}
    @Override public Something afterBarHook() {}
    @Override public Something beforeBazHook() {}
    @Override public Something afterBazHook() {}
}
于 2013-01-21T23:04:48.443 に答える
1

このパターンは、古いバージョンの Java で一般的でした。これは、インターフェースのデフォルト メソッドに代わる Java 7 です

Josh Bloch はこれをスケルトン実装と呼んでいます。通常、スケルトン実装は抽象的ですが、スケルトン自体で十分な場合は、クライアントにサブクラスの作成を強制する必要はありません。

Interface Segregation Principleを指摘する前の回答に同意します。スケルトン実装の必要性は、インターフェイスが「太りすぎ」であり、複数のジョブを実行しようとしている可能性があることを示すコードの匂いである可能性があります。このシナリオでは、ダミーまたは noop ロジックを使用して骨組みの実装を作成するよりも、インターフェイスを分割することをお勧めします。

于 2018-10-09T16:27:29.163 に答える
0

ヌルオブジェクトパターンについて質問していますか?

編集に加えて、MyClassオブジェクトはデフォルトの実装にすぎません。それを説明する特定のデザインパターンはないと思います。

于 2009-08-11T10:22:31.903 に答える
0

私には、これは特殊なケースまたはヌルオブジェクトパターンに最も近いように思われます。

あなたの更新は、テンプレートメソッドに似た何かがあなたが各テンプレートメソッドを呼び出す単一のメソッドを持っていないことを期待していることを示唆しています。

public void doEverything()
{
  doThis();
  doThat();
  done();
}
于 2009-08-11T10:26:13.613 に答える