本文討論介面卡模式。介面卡模式是23中設計模式之一,它的主要作用是在新介面和老介面之間進行適配。它非常像我們出國旅行時帶的電源轉換器。為了舉這個例子,我還特意去京東上搜了一下電源轉換器,確實看到了很多地方的標準不一樣。我們國家的電器使用普通的扁平兩項或三項插頭,而去外國的話,使用的標準就不一樣了,比如德國,使用的是德國標準,是兩項圓頭的插頭。如果去德國旅遊,那麼我們使用的手機充電器插頭無法插到德國的插排中去,那就意味著我們無法給手機充電。怎樣解決這個問題呢?只要使用乙個電源轉化器就行了。如下圖所示:
該介面卡下面的插頭符合德國標準,可以插到德國的插排中去,上面提供的介面符合國標,可以供我們的手機充電器使用。
下面我們使用**來表述介面卡模式:
**中有兩個介面,分別為德標介面和國標介面,分別命名為dbsocketinte***ce和gbsocketinte***ce,此外還有兩個實現類,分別為德國插座和中國插座,分別為dbsocket和gbsocket。為了提供兩套介面之間的適配,我們提供了乙個介面卡,叫做socketadapter。除此之外,還有乙個客戶端,比如是我們去德國旅遊時住的一家賓館,叫hotel,在這個德國旅館中使用德國介面。
德標介面:
/**
* 德標介面
*/publicinte***ce dbsocketinte***ce
德國插座實現德國介面
/**
* 德國插座
*/publicclass dbsocket implementsdbsocketinte***ce
}
?
德國旅館是乙個客戶端,它裡面有德標的介面,可以使用這個德標介面給手機充電:
/**
* 德國賓館
*/publicclass hotel
publichotel(dbsocketinte***ce dbsocket)
publicvoid setsocket (dbsocketinte***ce dbsocket)
//旅館中有乙個充電的功能
publicvoid charge()
}
現在寫一段**進行測試:
publicclass test
}
?
執行程式,列印出以下結果: 使用兩項圓頭的插孔供電
現在我去德國旅遊,帶去的三項扁頭的手機充電器。如果沒有帶電源介面卡,我是不能充電的,因為不可能為了我乙個旅客而為我更改牆上的插座,更不可能為我專門蓋一座使用中國國標插座的賓館。因為人家德國人一直這麼使用,並且用的挺好,俗話說入鄉隨俗,我就要自己想辦法來解決問題。對應到我們的**中,也就是說,上面的hotel類,dbsocket類,dbsocketinte***ce介面都是不可變的(由德國的客戶提供),如果我想使用這一套api,那麼只能自己寫**解決。
下面是國標介面和中國插座的**。
國標介面:
/**
* 國標介面
*/publicinte***ce gbsocketinte***ce
?
中國插座實現國標介面:
/**
* 中國插座
*/publicclass gbsocket implementsgbsocketinte***ce
}
可以認為這兩個東西是我帶到德國去的,目前他們還不能使用,因為介面不一樣。那麼我必須建立乙個介面卡,這個介面卡必須滿足以下條件:
1 必須符合德國標準的介面,否則的話還是沒辦法插到德國插座中; 2 在呼叫上面實現的德標介面進行充電時,提供一種機制,將這個呼叫轉到對國標介面的呼叫 。
這就要求: 1 介面卡必須實現原有的舊的介面 2 介面卡物件中持有對新介面的引用,當呼叫舊介面時,將這個呼叫委託給實現新介面的物件來處理,也就是在介面卡物件中組合乙個新介面。
下面給出介面卡類的實現:
publicclass socketadapter
implementsdbsocketinte***ce
/*** 將對就介面的呼叫適配到新介面
*/@override
publicvoid powerwithtworound()
}
這個介面卡類滿足了上面的兩個要求。下面寫一段測試**來驗證一下介面卡能不能工作,我們按步驟一步步的寫出**,以清楚的說明介面卡是如何使用的。
1 我去德國旅遊,帶去的充電器是國標的(可以將這裡的gbsocket看成是充電器)
gbsocketinte***ce gbsocket = newgbsocket();
2 來到德國後, 找到一家德國賓館住下 (這個賓館還是上面**中的賓館,使用的依然是德國標準的插口)
hotel hotel = newhotel();
3 由於沒法充電,我拿出隨身帶去的介面卡,並且將我帶來的充電器插在介面卡的上端插孔中。這個上端插孔是符合國標的,我的充電器完全可以插進去。
socketadapter socketadapter = newsocketadapter(gbsocket);
4 再將介面卡的下端插入賓館裡的插座上
hotel.setsocket(socketadapter);
5 可以在賓館中使用介面卡進行充電了
hotel.charge();
上面的五個步驟就是介面卡的使用過程,下面是完整的測試**。
publicclass testadapter
}
?
執行上面的程式,列印出以下結果: 使用三項扁頭插孔供電
這說明介面卡起作用了,上乙個例項中列印的是:使用兩項圓頭的插孔供電。 現在可以使用三項扁頭插孔供電了。我們並沒有改變賓館中的德標插口,提供了乙個介面卡就能使用國標的插口充電。這就是介面卡模式的魅力:不改變原有介面,卻還能使用新介面的功能。
由於上面的**都是分片的,沒有完整的專案
原始碼,為了使讀者對示例中的類和介面更清晰,下面給出uml類圖:
根據上面的示例,想必讀者應該能比較深入的了解到了介面卡模式的魔力。下面給出介面卡模式的定義(該定義來自於《head first 設計模式》):
介面卡模式將乙個類的介面轉換成客戶期望的另乙個介面,讓原本不相容的介面可以合作無間。
下面給出介面卡模式的類圖(該類圖同樣來自於《head first 設計模式》):
介面卡模式的三個特點:
1 介面卡物件實現原有介面 2 介面卡物件組合乙個實現新介面的物件(這個物件也可以不實現乙個介面,只是乙個單純的物件) 3 對介面卡原有介面方法的呼叫被委託給新介面的例項的特定方法
有人認為講解設計模式的例子都太簡單,看著感覺是那麼回事,但是要是真想在專案開發中使用,還真是應用不到。其實我們不必在專案中刻意使用設計模式,而是應該從實際的設計問題出發,看哪個模式能解決我們的問題,就使用哪個模式。不要為了使用模式而使用模式,那樣就捨本逐末了,一般情況下,只要遵循一定的設計原則就可以了,設計模式也是根據這些原則被總結出來的,熟悉了這些原則,模式自然而然就有了。
介面卡模式(類介面卡 物件介面卡)
做個筆記 引用 public inte ce usb public inte ce psp public class usber implements usb 類介面卡 psp適用usb介面 public class usbadapter extends usber implements psp 物...
介面卡模式 預設介面卡,類介面卡,物件介面卡
模式思想 改變乙個類的對外介面 增加或減少 以滿足不同外部呼叫者的需求 角色成員 目標介面 target 客戶所期待的介面。目標可以是具體的或抽象的類,也可以是介面。需要適配的類 adaptee 需要適配的類或適配者類。介面卡 adapter 通過包裝乙個需要適配的物件,把原介面轉換成目標介面。適配...
設計模式 介面卡模式 類介面卡 物件介面卡
乙個小例子,便於理解,上 這是我們造的。現在想用這個方法。public class adaptee 類介面卡。對我們想要的方法封裝一下,target就能像之前一樣,呼叫request方法即可。public class adapter1 extends adaptee implements targe...