前陣子開發了三支產 Word 文件的功能,一開始看了一下範本跟資料,很直覺的把整份文件作為一個範本,再把資料塞進該範本產出最後的文件,不過後來使用者需求調整了好幾次,所以又在這三支功能根據各自需求加上頁碼、空白頁、封面、合併內容 ... 等,經歷這幾次的調整後,不知道下一次使用者又要加什麼,有鑑於此,應該要想個好辦法替需求變動留一點彈性,這時就該派上 Decorator Pattern 來預留一下後路。
[word文件1]會有封面頁面、出席人員頁面、會議記錄頁面,其中會議記錄頁面需要有頁碼。
[word文件1]會有兩個封面頁面(分別在第一頁與最後一頁)、空白頁面、附件頁面,其中附件頁面需要有頁碼。
這種寫法在一個大方法做太多事情,若經過一段時間又要回來需求調整,勢必要整個程式碼重新 審視與理解,另一方面若大方法內有通用區域變數,調整需求時有可能改 A 影響到 B 的情況發生,有些人可能會覺得把這個大方法抽成多個小方法,但他們還是在同一個Class內,且架構不清晰,時間久了容易忘記他們是如何交互作用的,再者,若其中一些方法會用到其他lib,以相依性來看是整個Class都相依於該lib,相依性不夠精準,對於未來重構或是Debug來說可能會是一些負擔。
所以用 Decorator 來實作可以有效隔離程式碼,提高內聚,架構清晰,重用一些相同功能以及組合不同物件產生不同文件以因應未來的需求變化。簡單回顧一下Decorator pattern 的類別圖,主要有兩個角色,一個「基本元件(ConcreteComponent)」與「裝飾者(Decorator)」,他們都是一個「元件(Component)」,所以裝飾者可以在這些元件的操作前後做一點事情來組合出最終的元件。
接著各個基本元件只需專注產生原始資料,裝飾者只要透過傳進來的Document物件專注處理自己的事務,處理完成後再回傳出去即可,最終產生一份文件的程式碼如下方所示。
https://gist.github.com/ChengYiWu/5fcda81fef27ce2ca81bd84d9875f1ca