3

私はEffectiveJavaを読んでいます。関数オブジェクトを戦略として使用することについて説明しているセクションには、以下の段落があります。

戦略インターフェースは、そのすべての具体的な戦略インスタンスのタイプとして機能するため、具体的な戦略をエクスポートするために具体的な戦略クラスを公開する必要はありません。代わりに、「ホストクラス」は、タイプが戦略インターフェイスであるパブリック静的フィールド(または静的ファクトリメソッド)をエクスポートでき、具象戦略クラスは、ホストのプライベートネストクラスにすることができます。

   // Exporting a concrete strategy
  class Host {
        private static class StrLenCmp
               implements Comparator<String>, Serializable {

        public int compare(String s1, String s2) {
            return s1.length() - s2.length();
        }
    }

    // Returned comparator is serializable
    public static final Comparator<String>
    STRING_LENGTH_COMPARATOR = new StrLenCmp();
    ... // Bulk of class omitted
  }        

私の質問は、上記の方法を使用することの特別な利点はありますか?具体的な戦略を公開して戦略をエクスポートすることの問題点は何ですか?

4

3 に答える 3

2

はいあります。この方法では、具象クラスではなくインターフェースを返すため、Comparatorインターフェースの具象実装を変更する場合でも、クライアントクラスを変更する必要はありません(これがインターフェースを使用する最も重要な理由だと思います)。

例えば:

//inside aClass

Comparator c = Host.STRING_LENGTH_COMPARATOR; //Programming against interfaces is different from:
StrLenCmp  c = Host.STRING_LENGTH_COMPARATOR; //programming against concrete class

将来、StrLenCmpを別の実装(NewStrLenCmpと呼びましょう)で変更するとします。インターフェイスComparatorに対してプログラムした場合は、aClassを変更する必要はありません。

Comparator c = Host.STRING_LENGTH_COMPARATOR; //still work because interface doesn't changed
NewStrLenCmp  c = Host.STRING_LENGTH_COMPARATOR; // problem: you need to modify the client class in order to use the new concrete type: bad idea
于 2011-11-03T10:27:25.120 に答える
2

これは、何かを公開するのと同じ問題です-カプセル化。

オブジェクトのスコープを可能な限り狭くすると、そのオブジェクトがどのように使用されるかを推論するのがはるかに簡単になり、メンテナンスが大幅に容易になります(privateオブジェクトは、見ているのと同じソースファイルでのみ使用できることはわかっていますが、真に使用することはできません。何人の人がpublicオブジェクトをどのように使用しているかを知っています)。

確かに、すべてをパブリックとして宣言すれば、すべてのJavaプログラムが機能します。しかし、それはパンドラの箱に少し似ています-何かへのアクセスを開いたら、それを取り戻すのは難しいです。

具体的な戦略を公開しないことで、他のクラスやアプリがそれを自分の目的に使用できないようにします。つまり、本格的で光沢のある安定した公開クラスとして設計することを心配する必要はありません。明確に定義されたインターフェース。今、自分に合ったものを書くだけで、後で好きなように変更する自由があることを知ることができます。

于 2011-11-03T10:27:57.107 に答える
2
  • 公開のものあなたのAPIです。コードを出荷し、後で戦略の実装を変更する必要がある場合は、コードを出荷したすべての人のAPIが事実上壊れています。

  • したがって、特に必要になるまで、すべてが可能な限り狭い範囲にある必要があります。

  • また、他の場所ではこの戦略を使用していないため、静的にネストされたクラスに配置します。

于 2011-11-03T10:30:33.580 に答える