此系列文章是我閱讀《Refactoring To Patterns》過程中實際演練的筆記。閱讀過程中發現若沒有相當的 Design Patterns、Refactoring 底子,此書真的不易閱讀,必須伴隨實際操作才能更理解每個步驟具體的方式,故在這記錄之餘也跟各位分享。
書中是使用 Java 的程式碼作為範例,而我比較熟稔 C#,所使用的演練環境為:Visual Studio 2017、ReSharper、VsVim。過程中會因應 ReSharper 的功能,所以有些許的調整以便更「優雅」的進行重構。
此篇是關於 7.3 Move Embellishment to Decorator 的具體演練。
此次的 smaple code 是我建立的,若有錯誤還請多包涵,詳細程式碼請見:https://github.com/mystic01/refactoringtopatterns。
以下,請搭配影片閱讀(數字表示影片時間):
- 做出
shouldDecode
的 get 及 set method。0:00
(我明白 C# 有 property 可用,但為了和書中盡可能一致,所以我還是做了 getter 和 setter)- 先使用 Encapsulate Field 做成 property。
- 轉換為 method。
- 修改 method 名稱,和書中相同。
- 將建構子改為 Creation Method。0:50
- 將建構子改為 private,使編譯出錯。
- 跳至編譯出錯處,直接將 new 改為 creation method,讓 creation method 可以半自動的產生出來。
- 修改 Creation Method,將
shouldDecode
為true
的情況委託給DecodingNode
處理。2:40- 直接在 Create Method 裡頭加入條件式,鍵入尚不存在的 DecodingString ,依然半自動的將之生出。
※ 3:32base()
的引數還得自己一個個鍵入,若有比較好的方式請不吝指教 <(_ _)>。 - 分別將
StringNode
與DecodingNode
的ShouldDecode()
hardcode 為false
與true
。 - 在
DecodingNode
overridetoPlainTextString()
,專門處理shouldDecode
為true
的情況。 StringNode
的toPlainTextString()
改為只處理shouldDecode
為false
的情況。- 刪除不再需要的
shouldDecode
。
- 直接在 Create Method 裡頭加入條件式,鍵入尚不存在的 DecodingString ,依然半自動的將之生出。
- 將
DecodingString
中toPlainTextString()
取得textBuilder
的方式改為委託base
,也就是StringNode
。7:30
- 在
DecodingString
中使用一delegateNode
來裝載StringNode
,取代上一步的base
。8:01
- 將
delegateNode
改為由外部傳入,而非在建構子之中產出。9:42- 刻意將
delegateNode
與 field 脫勾,使其成為一 local variable。 - 將
delegateNode
型態改為stringNode
。 - Introduce Parameter,將
delegateNode
抽取為引數。如此一來,呼叫端會自動生成 stringNode 傳入,無須自行逐一修改。 delegateNode = stringNode;
- 刻意將
- 將
DecoingString
變更為實做Node
。11:22- 修改建構子,無須呼叫
base()
,並使用 Safe Delete 逐一刪除不必要的引數。 - 實做 Node 中所有 method,其內容均由 delegateNode 處理。(開始有一種很裝飾的感覺啦!!)
※ 11:52 這一連串動作我覺得做的相當狼狽,有夠累,不知道有沒有更智慧的方式可以自動生成?
- 修改建構子,無須呼叫
打完收工! 這次也有很多地方都使用到,「先用再生」的技巧,才不會自己一個個參數鍵入的很狼狽~
以上還請各位多多指教 <(_ _)>
其他 Refacotirng To Patterns 影片請見:Refactoring To Patterns
不堪入目的練功過程:Refactoring To Patterns (exercise)