8

目的

Stringオブジェクトの不変リストとして使用するクラスを作成します。

アプローチ

単純な List < E>Collections.unmodifiableList(List<? extends T> list)でラップするのではなく、Google GuavaImmutableList<E>コレクションを活用することにしました。 >、ラップされていることを認識していません (ソース: ImmutableCollectionsExplained )。

要件

  • スレッド間で使用される「値ホルダー」となるクラス
  • 作成後に内部値を変更するコードを許可しないでください

あると便利なもの

試み

より多くの組み合わせが可能ですが、ここでいくつかの試みを行います。ユーモラスな表現を許してください。

試み #1 (使用例を含む)

import java.util.List;
import com.google.common.collect.ImmutableList;
class BritnetSpearsSpellings implements Iterable<String> {
  public static BritnetSpearsSpellings of(String... spellings) {
    BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings();
    britneySpears.spellings = ImmutableList.copyOf(spellings);
    return britneySpears;
  }
  private List<String> spellings;
  private BritnetSpearsSpellings() {
  }
  public List<String> getSpellings() {
    return spellings;
  }
}
@Override
public Iterator<String> iterator() {
  return spellings.iterator();
}
public class Usage {
  public static void main(String[] args) {
    for (String sepllin : BritnetSpearsSpellings.of("Brittany Spears", "Brittney Spears", "Britany Spears"))
      System.out.printf("You spel Britni like so: %s%n", sepllin);
    }
  }
}

試み #2

class BritnetSpearsSpellings implements Iterable<String> {
  public static BritnetSpearsSpellings of(String... spellings) {
    BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings();
    britneySpears.spellings = ImmutableList.copyOf(spellings);
    return britneySpears;
  }
  private ImmutableList<String> spellings;
  private BritnetSpearsSpellings() {
  }
  public ImmutableList<String> getSpellings() {
    return spellings;
  }
  @Override
  public Iterator<String> iterator() {
    return spellings.iterator();
  }
}

試み #3

class BritnetSpearsSpellings implements Iterable<String> {
  public static BritnetSpearsSpellings of(String... spellings) {
    BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings(ImmutableList.copyOf(spellings));
    return britneySpears;
  }
  private final ImmutableList<String> spellings;
  private BritnetSpearsSpellings(ImmutableList<String> spellings) {
    this.spellings = spellings;
  }
  public ImmutableList<String> getSpellings() {
    return spellings;
  }
  @Override
  public Iterator<String> iterator() {
    return spellings.iterator();
  }
}

相違点のまとめ

  • 1 はList<E>をパブリック インターフェイスに保持し、JavaDoc で不変性を文書化します。

  • 2 Google GuavaImmutableList<E>としてすべてを保存および公開します

  • 3 特殊なコンストラクターを作成することを犠牲にして、内部参照を final として保持します。他の初期化オプション (実際には実際のクラスにあります) がない場合、静的ファクトリ メソッドの初期化がばかげているように見える可能性があります。

質問

選択の背後にある理由とともに、これらの実装のいずれかを選択するのを手伝ってください。

アプローチ#2の主な欠点は、クライアントが特殊なGoogle Guavaタイプを認識/可視化する必要があり、おそらくすべきではないことだと思いますか?

4

3 に答える 3

3

明らかに、私の意見では#3が最良の選択です。finalクラス(のそのフィールド)の不変性を強制し、文書化しますList。それ自体が不変であるという事実だけではありません。

Listをいくつかのjavadocで公開するかImmutableList、ゲッターで実際に公開するかは別のことです。ドキュメントを返すことの意図が明確であるという意見を見てきましたImmutableListが、それでも、低レベルで将来変更する必要がある可能性のあるもののインターフェイスではなく、実装に縛られています(不変性が「一般的に」であっても)良い)。したがって、これは1つのユースケースよりも、アプリケーションのグローバルな設計上の選択です。を使用する場合ImmutableList、それはクライアントにとって実際の問題ではないと思います。名前は明示的であり、IDEから簡単に確認でき、の実装であるListことがわかります。さらに情報が必要な場合は、javadocにアクセスできます。そして、誰が知っているか、彼らはそれを好きで、それを使い始めるかもしれません、

于 2012-09-18T09:52:33.570 に答える
1

問題のステートメント (「特定の文字列セットにはクラスが 1 つしかないはずです」) から、本当に必要なのはInterner<ImmutableSet<String>>.

  • InternerInterners.newStrongInterner()は、特定のデータを持つオブジェクトのインスタンスが 1 つだけであることを保証するためのユーティリティです ( で構築します)。
  • コレクションが不変であり、メンバーシップ テストをサポートする任意の順序のコレクションである場合は、ImmutableSetが適切な選択です。

または、Cache<ImmutableSet<String>>(詳細については、キャッシュの説明を参照してください) を確認することもできます。

于 2012-09-18T21:34:20.923 に答える
0

I would use Attempt #2 over Attempt #1, because it documents that you always return ImmutableList instances. In general it is useful to choose return types as specific as possible and parameter types as general as possible. But for both cases prefer Interfaces over concrete classes.

Well, ImmutableList is an abstract class and not an interface. But due to its nature it is acting very much like an interface.

Attempt #3 makes sense when your class member reference spellings cannot change for the object's lifetime and/or you want to get the whole class itself immutable. Otherwise when spellings can be assigned to another ImmutableList during the objects lifetime then it does not make sense.

Given the use case in your example I tend to say #3 is the best choice.

于 2012-09-18T09:50:27.213 に答える