などの単一のメソッドをSpring
持つ多くのインターフェイスを使用する多くのライブラリで見てきました。BeanNameAware
そして、実装者クラスは、単一のメソッドで多くのインターフェースを実装します。
単一のメソッド インターフェイスを維持することが理にかなっているのは、どのようなシナリオですか? たとえば、単一のインターフェイスがかさばることを避けるために行われますResultSet
か? それとも、これらのタイプのインターフェースの使用を推奨する設計基準はありますか?
などの単一のメソッドをSpring
持つ多くのインターフェイスを使用する多くのライブラリで見てきました。BeanNameAware
そして、実装者クラスは、単一のメソッドで多くのインターフェースを実装します。
単一のメソッド インターフェイスを維持することが理にかなっているのは、どのようなシナリオですか? たとえば、単一のインターフェイスがかさばることを避けるために行われますResultSet
か? それとも、これらのタイプのインターフェースの使用を推奨する設計基準はありますか?
Java 8 では、単一のメソッド インターフェイスを維持することは非常に便利です。これは、単一のメソッド インターフェイスがクロージャーと「関数ポインター」の使用を許可するためです。したがって、コードが単一のメソッド インターフェイスに対して記述されている場合は常に、クライアント コードは、匿名クラスを作成する代わりに、クロージャーまたはメソッド (単一のメソッド インターフェイスで宣言されたメソッドと互換性のあるシグネチャを持っている必要があります) を渡すことができます。対照的に、複数のメソッドを持つ 1 つのインターフェイスを作成すると、クライアント コードにはその可能性がなくなります。インターフェイスのすべてのメソッドを実装するクラスを常に使用する必要があります。
したがって、一般的なガイドラインとして、次のように言うことができます。クライアント コードに 1 つのメソッドのみを公開するクラスが一部のクライアントにとって有用である場合、そのメソッドに対して 1 つのメソッド インターフェイスを使用することをお勧めします。これに対する反例はインターフェイスです。ここでは、メソッドなしでメソッドIterator
のみを使用しても役に立ちません。これらのメソッドの 1 つだけを実装するクラスを持つことは役に立たないため、このインターフェイスを分割することはここではお勧めできません。next()
hasNext()
例:
interface SingleMethod{ //The single method interface
void foo(int i);
}
class X implements SingleMethod { //A class implementing it (and probably other ones)
void foo(int i){...}
}
class Y { //An unrelated class that has methods with matching signature
void bar(int i){...}
static void bar2(int i){...}
}
class Framework{ // A framework that uses the interface
//Takes a single method object and does something with it
//(probably invoking the method)
void consume(SingleMethod m){...}
}
class Client{ //Client code that uses the framework
Framework f = ...;
X x = new X();
Y y = new Y();
f.consume(x); //Fine, also in Java 7
//Java 8
//ALL these calls are only possible since SingleMethod has only ONE method!
f.consume(y::bar); //Simply hand in a method. Object y is bound implicitly
f.consume(Y::bar2); //Static methods are fine, too
f.consume(i -> { System.out.println(i); }) //lambda expression. Super concise.
//This is the only way if the interface has MORE THAN ONE method:
//Calling Y.bar2 Without that closure stuff (super verbose)
f.consume(new SingleMethod(){
@Override void foo(int i){ Y.bar2(i); }
});
}
たった 1 つ (または少数) のメソッドを持つインターフェースは、非常に有用なStrategy パターンの鍵です。これは、「これらのタイプのインターフェースの使用を推奨する設計標準」です。
もう 1 つの一般的なシナリオは、コールバックが必要な場合です。Foo は Bar を非同期タスクとして呼び出し、Bar が何かを完了すると、コールバックを使用して結果が Foo に返されます。コールバックは、メソッドを 1 つだけ含むインターフェイスにすることができます。(この例は、Android の多くのリスナー、Swing のイベント リスナーです...)
また、互いに密接に結合された 2 つのクラスがある場合 (それらを Foo と Bar と呼びましょう)。Foo は Bar のメソッドのほぼすべてを使用しますが、Bar は Foo のいくつかのメソッドのみを必要とします。Foo はそれを実装FooInterface
してから Bar に送信できます。Bar は FooInterface のみを認識し、実装クラスに含まれる他のメソッドは気にしないため、結合が緩くなりました。
単一のメソッド インターフェイスを維持することが理にかなっているのは、どのようなシナリオですか?
このようなシナリオでは、メソッドが 1 つだけのインターフェイスが必要です。
インターフェイスは、いくつかのクラスの共通の動作をカプセル化するために使用されます。したがって、クラス メソッドの限られたセットのみを呼び出す必要があるコード内の場所がいくつかある場合は、インターフェイスを導入する必要があります。メソッドの数は、正確に何を呼び出す必要があるかによって異なります。1 つのメソッドが必要な場合もあれば、 2つ以上のメソッドが必要な場合もあれば、メソッドがまったく必要ない場合もあります。重要なのは、動作を実装から分離できることです。
Favor Composition over Inheritance
本のチュートリアルではHead First Design Pattern
、機能をクラスに動的に追加するためにこのアプローチを推奨しています。以下のケースを見てみましょう:
public interface Quackable {
public void quack();
}
public class Quacks implements Quackable {
public void quack(){
//quack behavior
}
}
public class DontQuack implements Quackable {
public void quack(){
//dont quack
}
}
public class QuackableDuck{
Quackable quack; //add behavior dynamicall
}
そのため、QuackableDuck クラスは機能を動的に追加できます。
quack = new Quacks();
//or
quack = new DontQuack();
同様に、クラスに複数の動作を動的に追加できます。