(圖片來自: http://sourcemaking.com/)
以下為學習 Organizing Data 的筆記.
Change Bidirectional Association to Unidirectional
兩個 Class 之間有一個雙向的關聯,但其中一個 Class 並無使用到另一個 Class . 將其雙向關聯改成單向關聯.
優點: 降低維護時遭遇的複雜度/耦合度.
Change Reference to Value
如果 Reference Object 很小,很難管理,是不可變性(Immutable)的. 可以把它轉成 Value Object.
以 Java 的 String 來解釋 書中這段解釋不可變性的句子:
you need to replace the existing String object with a new String object rather than changing the content on an exisiting String object.
String msg = "Hi!";
msg.concat("Jack!"); // 直接修改原本的 String .
System.out.print(msg); // 印出"Hi!".
msg = msg.concat("Jack!"); // 用新的 String 取代.
System.out.print(msg); // 印出"Hi!Jack!".
Value Object:
- 最好是不可變性的. 如果是可變性的,得保證修改某個 Value Object ,其它所有代表同一事物的 Value Object 也得被修改,此時還不如使用 Refernce Object(大家都指向同一個物件位址).
- 在分散或同步的環境下是很有用的.
範例解釋:
修改前: Currency Class 利用類似 Factory Method Pattern 回傳合適的 Currency ,整個系統只會有一個 Currency 代表 Currency("USD").
因為 Currency 自身維護系統內所有的 Currency 物件,為此將建構子設為 private. -> 造成使用上的不便!? 所以改成 Value Object !? Orz
修改後: 整個系統能有多個 Currency 代表 Currency("USD").
Change Unidirectional Association to Bidirectional
兩個 Class 之間需要使用彼此的功能,但只有單方向的關聯時,加上 Back Pointer ,然後改寫管理兩邊關聯性的方法,使其方法同步修改兩個 Class 彼此間的關聯.
Change Value to Reference
當你有一個 Class ,它有很多相同的實體,而你想要簡化成單一實體時,將 Value Object 轉成 Refernce Object.
- Reference Object 就像是客戶/帳號. 每一個 Reference Object 都代表一個存在於真實世界的物件,你必須透過物件身份(Call by Reference)去比對是否相等. ex: 同一家銀行不可能兩個人擁有同一組帳號.
- Value Object 就像是日期/金錢. 它們完全是根據數量來定義. 你完全不用在意有多少個備份存在於系統. 你不用藉由比對 兩個物件是否一樣(同一個物件) 來確定兩物件是否相同,而只需要覆寫 equal() 和 hashCode(),比對兩物間中你想比對的值(成員變數...). ex: 你可以有一張100元,別人也可以有一張100元,不會有兩個人指向同一張100元.
- 並不總是很明顯能判斷何時用 Reference / Value .
Duplicate Observed Data
GUI 流程中會產生資料物件的概念,有需要一些跟存取資料相關的方法. 產生一個物件去保存資料,利用 Observer Pattern 來同步 GUI 層/資料層 這兩份資料.
優點: 簡化 UI 的程式碼. 將邏輯和 UI 分開.
Encapsulate Collection
若方法直接回傳 Collection(ex: ArrayList, Set ...),改成回傳不允許修改的 Collection(ex: unmodifiableCollection ...) 並提供 add/remove 的方法.
List friendList = alex.getFriends(); // 回傳整個 List.
friendList = new ArrayList(); // Alex 的朋友清單被別人整個置換而不自知. 在複雜的系統內,這會是一個很難找的的 Bug.
優點: 隱藏資料集合的實作細節. 管理資料集合的操作集中在原本擁有者身上.
Encapsulate Field
將 public 欄位改成 private 欄位,並提供存取方法. Orz -很基本
Organizing Data
Page not Found
Replace Array with Object
幹! 這篇應該要 mail 給我前輩啊!!!
當你有一個陣列,裡頭的元素代表不同的事物時,將 陣列 轉成 物件,陣列內的元素 轉成 物件內的欄位(成員變數).
當你發現你說出 "串列中第三個元素裝的是員工的家庭成員陣列..." 類似的話,相信我! 你應該是在找死! RD 的腦不應該是在裝這些細節啊~!!
優點: 讓 RD 的腦少裝點沒用的東西.
Replace Data Value with Object
Class 內含有一個需要額外行為或其它資料的資料項目時,將其資料項目抽出建立新的物件.
優點: 將責任分散,每個物件只專注在自己該負責的事物上.
Replace Magic Number with Symbolic Constant
程式碼中不要有魔術數字,用常數來替換它.
Replace Record with Data Class
請參考 Replace Array(算是 Record 的一種形式) with Data Object .
Replace Subclass with Fields
子類別間的差異只在於回傳不同資料答案的方法,此時將該方法移至父類別,並刪除衍生的子類別.
- 有 "行為" 不同於父類別 -> 建立子類別
- 有 "特性(欄位)" 不同於父類別 -> 不需建立子類別,在父類別利用 Map 來動態儲存變動的特性. 如此就不用維護一堆看起來沒什麼差異的子類別.
Replace Type Code with Class
類別內含有不影響其行為的 Type Code (ex: off = 0, on = 1 ...),產生一個新的 Class 去紀錄這些 Type Code .
優點: 將 Type Code 放置更合適的地方. Type Code 實際對應的值被隱藏起來.
Replace Type Code with State/Strategy
有會影響其行為的 Type Code 而沒有使用子類別,使用 State Pattern / Strategy Pattern 建立對應 Type Code 的子類別.
Replace Type Code with Subclasses
有會影響其行為的 Type Code(Immutable) 而沒有使用子類別,建立對應 Type Code 的子類別.
Self Encapsulate Field
直接存取成員變數 vs 間接存取成員變數
延伸閱讀: http://www.blogjava.net/ivanwan/category/2732.html?Show=All
0 則回應: