天天看點

設計模式:擴充卡模式(Adapter)

 擴充卡模式:将一個類的接口轉換成客戶希望的另外一個接口。擴充卡模式使得原本由于接口不相容而不能一起工作的那些類可以一起工作。

 擴充卡模式有類擴充卡模式和對象擴充卡模式兩種不同的形式。

類擴充卡

 類擴充卡模式把适配的類的API轉換成目标類的API

設計模式:擴充卡模式(Adapter)

 擴充卡模式所涉及的角色:

目标角色(Target): 這就是所期待得到的接口。

源角色(Adaptee):需要适配的接口

擴充卡角色(Adapter):擴充卡類是本模式的核心。擴充卡把源接口轉換成目标接口。顯然,這一角色不可以是接口,而必須是具體類。

舉個簡單例子:

1 目标角色

2 源角色

3 擴充卡角色(類擴充卡決定了Target不能為類,隻能為接口,因為java不支援多繼承的關系)

4 測試代碼

對象擴充卡

舉個簡單例子

目标角色(同上,這裡的目标角色Target可以為類)

源角色(同上)

擴充卡角色

4.測試代碼:

類擴充卡和對象擴充卡的權衡

類擴充卡使用對象內建的方式,是靜态的定義方式;而對象擴充卡使用對象組合的方式,是動态組合的方式。

對于類擴充卡,由于擴充卡直接繼承了Adaptee,使得擴充卡不能和Adaptee的子類一起工作,因為繼承是靜态的關系,當擴充卡繼承了Adaptee後,就不能再取處理Adaptee的子類了。對于對象擴充卡,一個擴充卡可以把多種不同的源适配到同一個目标。換言之,同一個擴充卡可以把源類和它的子類都适配到目标接口。因為對象擴充卡采用的是對象組合的關系,隻要對象類型正确,是不是子類都無所謂。

對于類擴充卡,擴充卡可以重定義Adaptee的部分行為,想當于子類覆寫父類的部分實作方法。對于對象擴充卡,要重定義Adaptee的行為比較困難,這種情況下,需要定義Adaptee的子類來實作重定義,然後讓擴充卡組合子類。雖然重定義Adaptee的行為比較困難,但是想要增加一些新的行為則友善的很,而且新增加的行為可同時适用于所有的源。

對于類擴充卡,僅僅引入了一個對象,并不需要額外的引用來間接得到Adaptee,對于對象擴充卡,需要額外的引用來間接得到Adaptee。

總結:建議盡量使用對象擴充卡的實作方式,符合CARP原則。

Jdk中的擴充卡模式 java.util.Arrays#asList() java.io.InputStreamReader(InputStream) java.io.OutputStreamWriter(OutputStream)

總結

 優點:更好的複用性:系統需要使用現有的類,而此類的接口不符合系統的需要。那麼通過擴充卡模式就可以讓這些功能得到更好的複用。更好的擴充性:在實作擴充卡功能的時候,可以調用自己開發的功能,進而自然地擴充系統的功能。

 缺點:過多的使用擴充卡,會讓系統非常零亂,不易整體進行把握。如果不是很有必要,可以不使用擴充卡,而是直接對系統進行重構。

适用場景

你想使用一個已經存在的類,而它的接口不符合你的需求

你想建立一個可以複用的類,該類可以與其他不相關的類或不可預見的類協同工作。

(僅使用與對象Adapter)你想使用一些已經存在的子類,但是不可能對每一個都進行子類化以比對它們的接口。

預設擴充卡

 當你想實作一個接口但又不想實作接口中所有的方法,隻想去實作一部分方法時,就用到了預設擴充卡模式。它的方法時在接口和具體實作類中添加一個抽象類,而用抽象類是實作目标接口的所有方法。而具體的實作類隻需要覆寫其需要完成的方法即可。

舉個簡單案例:

1 接口類(有許多方法:吃,睡,工作以及鍛煉,但是我懶隻想吃喝睡)

2 抽象類:

3 實作類

參考資料