iT邦幫忙

2022 iThome 鐵人賽

DAY 22
0
自我挑戰組

設計模式探索系列 第 22

[Day 22] 轉接器與門面模式 (2)

  • 分享至 

  • xImage
  •  

物件轉接器與類別轉接器

類別轉接器的圖示則如下:

圖 1

所謂的類別轉接器需要用多重繼承來進行實作,可以看到圖中的差別,在於adapter在物件轉接器中,是實作target(鴨子),並將adaptee(火雞)保管在在其中,是在adapter透過保管其中的adaptee進行呼叫;而類別轉接器則是同時繼承target與adaptee,就可以直接進行呼叫。
我們來看看鴨子的例子中物件轉接器類別轉接器的對應角色:

圖 2

試著用C++使用類別轉接器來寫寫看前面鴨子的例子:

/*程式碼待補*/

以下再討論物件轉接器類別轉接器的差別:

  • 物件轉接器:
    • 因為使用組合,不但可以轉換adaptee,也可以轉換它的所有子類別。
  • 類別轉接器:
    • 僅能處理特定的adaptee,但不需要重新實作整個adaptee,因為透過繼承,可覆寫adaptee行為即可。

門面模式

這章還有一個新模式─門面模式 (Facade Pattern) ,這種模式也是在修改介面,但它的目的是:為了簡化介面
還記得前一章的派對模式嗎?有些操作是綁定常需要一起做的,例如看電影的一系列動作:

/*程式碼待補*/

此時就可以使用門面模式─用一個簡單的介面來打理這些複雜的關係:

圖 3

是否很好理解呢?平常在程式設計中應該就時常把重複出現的動作寫成一個function,其實門面模式也是類似的意思,只是它是直接整理成一個 "類別" ,而內容橫跨各種不同類別的互動操作。
順帶一提,雖然門面將子系統類別集合在一起,但並未"封裝"子系統的類別,如果想使用子類別的特定操作,還是可以直接使用,這也是門面模式的特色─ 雖然提供了簡化介面,但還是公開系統的所有功能。
例如看電影就可以創建為門面系統的其中一個方法:

/*程式碼待補*/

門面模式定義

使用門面模式非常簡單,就是先例一個類別雷統一簡化一組複雜類別,沒有用到什麼抽象類別或介面等等,但還是可以避免用戶端與子系統的緊密耦合。
以下是門面模式的定義:

門面模式為一個子系統裡面的一組介面提供一個統一的介面。門面定義了高階的介面,可讓子系統更容易使用

門面模式的類別圖如下:

圖 4

第七個原則

接著則是好久~沒有登場的原則了!這條原則是 "最少知識原則"

最少知識原則:只與最親近的朋友交談。

這章連原則都非常簡單XD 意思就是,在設計系統時要注意每個物件與多少個類別互動,以及互動方式,要避免讓大量的類別耦合在一起。而要做到此點,就是在物件的方法裡只呼叫以下這些東西的方法

  • 物件本身
  • 用參數傳給該方法的物件
  • 該方法建立或實例化的任何物件
  • 該物件的任何組件 (HAS-A)

簡而言之,要避免使用呼叫其他方法後 "回傳的物件" 的方法,因為這樣等於對另一個物件的component發出請求,就需要認識更多物件。以下是舉例:

  • 違反原則:
/*程式碼待補*/
  • 遵守原則:
/*程式碼待補*/

以下則是使用此原則的呼叫這四類東西方法的案例:

/*程式碼待補*/

這個原則也有被稱作 "Law of Demeter" 。另外,這個原則的副作用就是需要寫出更多進行 "包裝" 的類別,雖然可以減少軟體的維護成本,但可能會增加複雜度並降低執行期的效能;因此再一次,這些原則的運用都是要在最可能變化的地方去斟酌使用!

門面模式與最少知識原則

為何說門面模式雖簡單卻降低了耦合關係呢?因為運用了門面模式後,用戶端只需要認識我們新創的門面類別即可!如在看電影的範例中,Client僅需認識HomeTheaterFacade這個類別即可!未來若設備要改變,門面模式也可以維持對用戶端的介面,修改門面類別的操作即可。而若子系統中太過複雜,也可以再建立一些子系統階層的門面。

結語

這章非常直觀也很好實作,一下又收穫了兩種模式一個原則,可以快速地邁入下一章啦~


上一篇
[Day 21] 轉接器與門面模式 (1)
下一篇
[Day 23] 在VS Code使用C++
系列文
設計模式探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言