2010-11-15 93 views
1

現在我有被傳遞到實現ContainerOfThings類的getStuff(Message)方法約60 Message類型。有這兩種實現方法getStuff(Message)生成基於構件變量的字符串的ContainerOfThingsBoxOfStuffBagOfTricks的多種變型。結果也可能包含預先申請或後續數據,如標籤或連鎖數據。見下面的代碼。映射到動態串

public class BoxOfStuff implements ContainerOfThings 
{ 
    private String var1; 
    private String var2; 
    private String varN; 

    public String getStuff(Message message) 
    { 
     if (message.equals(Message.GET_STUFF1)) 
      return var1; 
     else if (message.equals(Message.GET_STUFF2)) 
      return "Var2 is: " + var2; 
     else if (message.equals(Message.GET_STUFFN)) 
      return varN + "\n"; 
     // Etc. for each Message.GET_* 
    } 
    // getters and setters for each var* 
} 

public class Message 
{ 
    private String id = null; 

    private Message(String id) 
    {  this.id = id; } 

    public final String toString() 
    {  return this.id; } 

    public static final Message GET_STUFF1 = new Message("V1"); 
    public static final Message GET_STUFF2 = new Message("V2"); 
    public static final Message GET_STUFFN = new Message("VN"); 

} 

我試圖找到一個滿足以下目標的設計。 (1)從getStuf()返回的字符串需要反映實現類的成員字段的當前狀態。 (2)此外,我寧願遠離一個令人難以置信的長系列if/else if塊。一個令人擔憂的問題是易於改變爲持續的數據驅動的可配置對象方法,其中Map適用於這種方法。 (3)設計應該允許簡單的維護和/或編輯。這可以工作,但有一點凌亂

一個設計是創建在構造函數初始化所有鍵/值的地圖,並重置每個setter方法中的任何鍵/值對。通過這種方式,對getStuff(Message)的響應在更改後更新爲新內容(即:在setVar*()方法中)。任何其他想法?

+0

澄清:你想創建一個'地圖<信息,字符串>''那裏格式String'輸出? – 2010-11-15 23:00:45

+0

該字符串應該包含任何引用成員變量(調用getStuff()時的當前值)的當前值,並且具有任何前置或後置字符串數據。 – Aaron 2010-11-15 23:03:33

+0

消息類型的結果字符串的格式是否因IContainerOfThings實現而異? – 2010-11-15 23:16:23

回答

1

我認爲你需要兩張地圖。一個是Map<Message, String>,其中的值將是一個格式字符串(即將傳遞到String.format()的東西)。第二張地圖將是一個Map<Message, Field>,一旦你看看反射庫,這應該是相當自我解釋的。這些將需要在初始時設置,但在此之後,方法應該相當乾淨,並且您的設置者不會受到任何影響。

順便說一句,Java的一般不前綴與接口I

+0

我今天嘗試了一個類似於這個的實現。反射實現了具有輸出動態字符串的Map的預期效果。我看到的唯一潛在的維護問題是字段名稱重構時創建的不匹配。我會做一些閱讀,看看我能否找到一個處理這個問題的好方法。 – Aaron 2010-11-17 05:41:02

0

如何:

public abstract class BaseOfBox implements IContainerOfThings { 
    protected final Map<Message, String> stuffs = 
      new HashMap<Message, String>(); 

    public final String getStuff(Message message) { 
     return stuffs.get(message); 
    } 
} 

public class BoxOfStuff extends BaseOfBox { 
    private String var1; 
    private String var2; 

    public BoxOfStuff() { 
     super(); 
    } 

    public setVar1(String var1) { 
     this.var1 = var1; 
     stuffs.put(Message.GET_STUFF1, var1); 
    } 

    public setVar2(String var2) { 
     this.var2 = var2; 
     stuffs.put(Message.GET_STUFF2, "Var2 is: " + var2); 
    } 
    ... 
} 

坦率地說,我覺得這是一個非常醜陋的解決方案,但這樣的要求是,IMO。我懷疑只有在審查(實際)要求時才能找到更優雅的解決方案。

+0

我希望找到一個設計,其中(1)getStuff響應的計算可以按需執行;和(2)遠離O(n)if/else if系列。你們當然完成了#2。 – Aaron 2010-11-16 19:15:43

+0

好吧,也許你只需要'Message'實例擁有一個'enum'字段,這樣'getStuff()'就可以使用'switch'語句。 – 2010-11-16 22:15:33

+0

@Citizen:您的評論會明顯地澄清您的問題;你介意編輯你的問題來包括這個嗎?另外,如果'if'/else if塊不一定是O(n) - 根據你的測試,編譯器可能會做得比這更好。但這可能是一個有爭議的問題 - 除非你有成千上萬的'else if'語句,否則性能影響很可能是無關緊要的。 – 2010-11-17 00:52:50

1

我不是100%確定我理解您的問題,但聽起來好像您要調用getStuff()的結果。

執行此操作的一種簡單方法是使用類中的makeComputingMap()方法,該方法位於Google圖書館的Guava庫中。

例如,你可以這樣做:

Map<Message, String> map = new MapMaker() 
    .expireAfterWrite(10, TimeUnit.MINUTES) 
    .makeComputingMap(
     new Function<Message, String>() { 
     public String apply(Message message) { 
      // Your getStuff() implementation here 
     } 
     }); 

這是否有意義?

+0

絕對有趣...我喜歡它,但它似乎是一系列的if/else if語句只是移動到函數聲明的主體以填充緩存。 – Aaron 2010-11-16 17:50:47