[英]How to design an immutable value class holding java.lang.String?
創建一個用作String對象的不可變列表的類。
我決定利用Google Guava的ImmutableList <E>集合,而不是將簡單的List <E>與Collections.unmodifiableList(List <?擴展T>列表)包裝在一起,因為我知道這避免了對支持List <E的不必要的並發檢查> ,它不知道是否被包裝(來源: ImmutableCollectionsExplained )。
盡管可以進行更多組合,但是在此進行了一些嘗試。 原諒幽默的演繹。
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);
}
}
}
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();
}
}
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();
}
}
請幫助我在這些實現方式中選擇一種,並在選擇時提供您的推理依據。
我認為方法2的主要缺點是客戶需要具有專門的Google Guava類型的認知/可見性,也許他們不應該嗎?
顯然,我認為#3是最佳選擇。 final
強制並記錄了類(該字段)的不可變性,不僅限於List
本身是不可變的事實。
在getter中使用某些Javadoc公開List
還是實際的ImmutableList
是另一回事。 我已經看到了這樣的觀點,即返回ImmutableList
清楚地說明意圖,但是,您仍然將自己綁定到實現上,而不是接口上,這是一個很低的水平,將來可能需要更改(即使不可變性通常是“ ”)。 因此,對於您的應用程序而言,它不僅僅是一個用例,而是更多的全局設計選擇。 如果您確實使用ImmutableList
,那么我認為這對客戶端不是一個真正的問題,名稱是顯式的,可以通過您的IDE輕松地看到它是List
的實現,如果他們需要更多信息,他們可以訪問javadoc 。 誰知道,他們可能會喜歡它,並與Guava提供的所有其他優點一起開始使用它:-)
從問題陳述中(“一組給定的字符串應該只有一個類”),聽起來您真正想要的是Interner<ImmutableSet<String>>
。
Interners.newStrongInterner()
構造一個實用程序),用於確保您只有一個對象的任何實例以及任何給定的數據。 或者,您可能希望查看Cache<ImmutableSet<String>>
(有關詳細信息,請參見Caches Explained )。
我將使用Attempt #2
不是Attempt #1
,因為它記錄了您始終返回ImmutableList實例的情況。 通常,選擇盡可能具體的返回類型和盡可能一般的參數類型很有用。 但是對於這兩種情況,接口都比具體類更喜歡。
好吧, ImmutableList
是一個抽象類,而不是一個接口。 但是由於其性質,它的行為非常像界面。
當您的類成員引用spellings
在對象的生存spellings
無法更改和/或您希望使整個類本身不可變時, Attempt #3
有意義。 否則,當可以在對象生存期內將spellings
分配給另一個ImmutableList時,則沒有意義。
考慮到您的示例中的用例,我傾向於說#3是最佳選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.