2015-06-20 49 views
7

我正在創建一個應用程序,其中包含我正在編寫的名爲Person的類。 Person的其中一個字段是'別名',它是ArrayList<String>。最終,別名將根據以下邏輯顯示給用戶:如果Person具有別名,則它們應該被顯示爲[Finch, Wren, Admin, etc...],否則應該顯示UNKNOWN。到目前爲止,我已經試過三種方式之一實現這一點:如何處理ArrayList的默認值

  1. 人包含方法getAliases()它簡單的返回ArrayList中的副本是。調用者檢查一個空數組以實現所需的行爲。

  2. 人包含方法aliasesToString()可以調用它來產生所需的字符串。

  3. 而不是使用ArrayList<String>,別名是DefaultableArrayList<T>的實施。這個類擴展了ArrayList,並保留了一個默認值T和toString()方法被覆蓋以產生所需的字符串。該應用程序調用some_person.getAliases().toString()來產生所需的行爲。

下面是我實現選項3:

public class DefaultableArrayList<T> extends ArrayList<T> { 

    private static final long serialVersionUID = -6735356930885363889L; // Auto-generated 
    private final T defaultElement; 


    public DefaultableArrayList(T defaultElement) { 
     super(); 
     this.defaultElement = defaultElement; 
    } 


    public DefaultableArrayList(Collection<? extends T> c, T defaultElement) { 
     super(c); 
     this.defaultElement = defaultElement; 
    } 


    public DefaultableArrayList(int initialCapacity, T defaultElement) { 
     super(initialCapacity); 
     this.defaultElement = defaultElement; 
    } 


    public T getDefaultElement() { 
     return defaultElement; 
    } 


    @Override 
    public String toString() { 
     if (!isEmpty()) { 
      return super.toString(); 

     } else { 
      return defaultElement.toString(); 
     } 
    } 
} 

我關心的有關選項2和3的是,我可能同時違反OOP準則增加不必要的複雜性。如果沒有別名,人應該真的關心會發生什麼,並且確定別名如何最終在應用程序中實現時是否有意義?我認爲我應該讓呼叫者處理空箱子。我應該選擇哪種選項最符合標準OOP設計指南?還是有沒有第四個選項,我沒有考慮?

回答

6

第一個選項是正確的。該模型不應該關心它的顯示方式。

在豐富的應用程序,Web應用程序或控制檯應用程序中,您不會以同樣的方式表示此人和他/她的別名。

即使在給定的應用程序中,您可能會以各種方式表示相同的模型。

如果您將應用程序國際化,則必須將「UNKNOWN」更改爲其他內容。

所以,只需返回列表(或列表的不可修改vew),並讓表示層處理表示邏輯。順便說一下,toString()比用於在應用程序中表示對象的功能方法更像調試幫助。通過你的選擇

2

讓我們來看看:

人包含方法getAliases(),它簡單地返回 ArrayList的原樣。調用者檢查一個空數組以實現所需的行爲。

調用者代碼是什麼樣的?

if (!person.getAliases().isEmpty()) { //Print aliases } 

這看起來有點醜陋和難以理解。如果你想要去的這個選項,你至少可以做的是Person基本上不檢查你添加hasAliases方法,使客戶端代碼更易讀:

if (person.hasAliases()) { //Print aliases } 

這是一個很多更清潔和更大量可讀的代碼。

Person包含方法aliasesToString(),它可以被調用來產生所需的字符串。

雖然Person是自給自足的不是壞的。所有客戶端代碼所要做的就是調用person.aliasesToString()而不是做:

if (person.hasAliases()) { 
    List<String> aliases = person.getAliases(); 
    StringBuilder aliaseString = new StringBuilder(""); 
    for (String alias : aliases) { 
     aliasString.append(aliases); 
    } 
} 

而不是使用的ArrayList,別名是DefaultableArrayList

的實現,這對於這樣一個簡單的任務矯枉過正。

那麼你會採用哪種方法?這取決於您的總體要求。如果你有不同的客戶/ UI想要用別名做不同的事情,選項1將是最好的。如果您有一個總是希望以某種方式打印別名的單個客戶端,則選項2將是更好的選擇。

2

我覺得最簡單的方式往往是好風格。也就是說,在做簡單的事情時,代碼所得到的醜陋通常意味着該風格正在走向歧途。因此,選項1看起來是實現這一目標的堅實途徑。使用getAliases()返回或打印字段是相當標準的。此外,您可以實現對空數組的檢查,並在該實例中返回或打印UNKNOWN。否則,ArrayList toString()將負責格式化內容。

2

選項3是一種矯枉過正。我不會延長ArrayList這麼小的附加價值。

在選項1和選項2之間進行選擇取決於getAliases()返回的List是否有其他預期用途,而不是顯示它的字符串表示形式。

我看到aliasesToString()方法唯一的缺點是它假設Person類的所有用戶都會以相同的方式顯示別名。

如果使用getAliases()方法,我寧願使用該方法來返回該List的副本或該List的數組表示形式。原因是你阻止Person類的用戶通過變異由getAliases()返回的List來突變Person實例。

+2

我寧願返回一個不可變的視圖:'Collections.unmodifiableList(別名)'。 –

+0

@JBNizet'Collections.unmodifiableList(aliases)'是一個很好的選擇。它可以保護原始實例成員不被修改,並使方法的調用者清楚,他們不能通過變更別名列表來突變Person實例。 – Eran

+0

是的,當然,對不起,我不是故意暗示我會返回一個直接引用。這是一個疏忽。 – Helios