此系列文章是我閱讀《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。 - 在
DecodingNodeoverridetoPlainTextString(),專門處理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)



