Java設計模式之從[滑鼠介面][星際爭霸中的兵種行為]分析介面卡(Adapter)模式
介面卡將一個類的介面轉換成客戶希望的另外一個介面。下面用三個例子來反映介面卡的不同用途:
情況一:
我買了一個PS2介面的滑鼠,但是我的電腦沒有PS2的介面,僅有USB的介面。為了不浪費這個滑鼠,我跑到商店買了一個PS2到USB的轉接頭,這樣我就用上了PS2的滑鼠。USB轉接頭就是一個典型的介面卡。
interface USBPort {
void connect();
}
interface PS2Port {
void connect();
}
class USBMouse implements USBPort {
public void connect(){
System.out.println("滑鼠連線上了USB埠!");
}
}
class PS2Mouse implements PS2Port{
public void connect(){
System.out.println("滑鼠連線上了PS2埠!");
}
}
class PS22USBMouseAdapter implements USBPort{
private USBPort usbMouse;
public PS22USBMouseAdapter (PS2Port ps2Port){
System.out.println("正在將PS2介面轉換為USB介面...");
//在此處我們僅僅是新建了一個USBMouse物件,對於更加複雜的情況,我們可以對PS2Port的物件進行很多操作
usbMouse = new USBMouse();
}
public void connect(){
usbMouse.connect();
}
}
class Adapter1
{
public static void main(String[] args) {
PS2Mouse mouse = new PS2Mouse();
mouse.connect();
USBPort adapter = new PS22USBMouseAdapter(mouse);
adapter.connect();
}
}
PS22USBMouseAdapter是一個PS2到USB介面的介面卡,由於它最終輸出的是USB資訊,因此繼承了USBPort。我們最後例項化adapter時,它的型別是USBPort —— 設計模式就是如此,我們一般用物件的抽象來進行宣告和定義,而不是具體的類。PS22USBMouseAdapter實現了PS2介面向USB介面的轉變。
情況二:
星際爭霸中,人族的頂級兵種為戰鬥巡洋艦(Battlecruiser)。巡洋艦上有個技能叫做大和炮(Yamato gun)。
假設我們在設計巡洋艦的時候,並沒有想到它可以裝載大和炮,那麼我們的巡洋艦類(Battlecruiser)中僅有一個attack方法。後來我們希望給巡洋艦增加一個大和炮的技能,但是我們又不想修改巡洋艦類的程式碼,這個時候就可以用介面卡來實現,此時的介面卡可以理解成,我們在巡洋艦上裝一個轉換裝置,使得它可以安裝和發射大和炮。
class Battlecruiser{
public void attack(){
System.out.println("大和戰艦發起進攻!");
}
}
class YamatoAdapter extends Battlecruiser implements Yamato {
public void yamato(){
System.out.println("大和戰艦使用大和炮進行攻擊!");
}
}
interface Yamato{
void attack();
void yamato();
}
class Adapter2
{
public static void main(String[] args) {
Yamato superBattlecruiser = new YamatoAdapter();
superBattlecruiser.attack();
superBattlecruiser.yamato();
}
}
注意,Battlecruiser類是我們一開始就設計好的。為了能給巡洋艦裝上大和炮,我們新建了一個Yamato介面,這個介面有原來巡洋艦的attack方法,並且還增加了一個yamato方法。最後,建立一個繼承於巡洋艦的類YamatoAdapter,在測試類中用Yamato例項化一個巡洋艦,它既可以普通攻擊,又可以用大和炮進行攻擊。
你可能會想,明明YamatoAdapter已經繼承了Battlecruiser,為何還要繼承Yamato介面?原因如之前所說,我們用“介面”來定義物件,而不是用具體的類。
情況三:
我需要設計星際爭霸人族兵種的一些抽象過程。如,所有兵種都要繼承於一個介面,這個介面有attack、stop、move等方法。這也就意味著,任何一個兵種類都要實現attack、stop、move這三個方法。
這樣一來會有一個問題:並非所有的兵種都有attack、stop、move這3個行為。例如人族的醫療兵(Medic),她不具有attack行為(遊戲中她是無法攻擊敵人的);再例如人族的禿鷹戰車(Vulture,我們俗稱的佈雷車),它可以埋蜘蛛雷。蜘蛛雷在敵人靠近的時候,它才會進行自爆攻擊。也就是說,蜘蛛雷不具有stop和move方法,只具有attack方法。
可見,一旦介面的方法多了起來,我們為了實現它們得手工寫不少程式碼,要是其中若干方法是我們該類不會用到的,我們不得不寫一個空方法。為了減少程式碼編寫,這時,我們可以使用介面的介面卡模式:
interface StarcraftSoldier{
void attack();
void stop();
void move();
}
abstract class SoldierAdapter implements StarcraftSoldier {
public void attack(){}
public void stop(){}
public void move(){}
}
class SpiderMine extends SoldierAdapter {
public void attack(){
System.out.println("蜘蛛雷發現敵人,進攻!");
}
}
class Adapter3
{
public static void main(String[] args) {
new SpiderMine().attack();
}
}
介面的介面卡SoldierAdapter為介面StarcraftSoldier的所有方法做了空實現,在我們建立SpiderMine時,繼承SoldierAdapter,就不必將介面中的所有方法都實現一次了。
以上就是我所理解的介面卡的用途,我把它理解成一個相容裝置,或者轉換裝置。若有牽強的地方,歡迎大家指出。
相關文章
- 設計模式之介面卡模式(adapter pattern)設計模式APT
- PHP設計模式-Adapter 介面卡模式PHP設計模式APT
- Adapter 介面卡模式(設計模式03)APT設計模式
- 12/24 設計模式之介面卡模式 Adapter Pattern設計模式APT
- Java設計模式之介面卡模式Java設計模式
- 23種設計模式之介面卡模式設計模式
- Java設計模式之介面卡設計模式Java設計模式
- 《設計模式》 - 5. 介面卡模式( Adapter )設計模式APT
- 設計模式筆記:介面卡模式(Adapter)設計模式筆記APT
- Java設計模式之(八)——介面卡模式Java設計模式
- 設計模式的征途—7.介面卡(Adapter)模式設計模式APT
- Scala 與設計模式(五):Adapter 介面卡模式設計模式APT
- 人人都會設計模式:介面卡模式--Adapter設計模式APT
- C#設計模式-介面卡模式(Adapter Pattern)C#設計模式APT
- 設計模式——6介面卡模式(Adapter)設計模式APT
- 人人都會設計模式---介面卡模式--Adapter設計模式APT
- 設計模式--介面卡模式Adapter(結構型)設計模式APT
- 6.java設計模式之介面卡模式Java設計模式
- java23種設計模式——六、介面卡模式Java設計模式
- java設計模式-介面卡模式Java設計模式
- 設計模式之介面卡模式設計模式
- 設計模式之【介面卡模式】設計模式
- C#設計模式(7)——介面卡模式(Adapter Pattern)C#設計模式APT
- 介面卡模式(Adapter)模式APT
- Java設計模式(6)----------介面卡模式Java設計模式
- Java 設計模式(一)《介面卡模式》Java設計模式
- Java設計模式7:介面卡模式Java設計模式
- PHP 設計模式之介面卡模式PHP設計模式
- Javascript 設計模式之介面卡模式JavaScript設計模式
- 設計者模式之介面卡模式模式
- 設計模式系列之「介面卡模式」設計模式
- php模式設計之 介面卡模式PHP模式
- 23種設計模式(5)-介面卡模式設計模式
- 人人都會設計模式:04-介面卡模式–Adapter設計模式APT
- 設計模式之介面卡設計模式
- python設計模式之介面卡模式Python設計模式
- C#設計模式之介面卡模式C#設計模式
- Rust語言之GoF設計模式:介面卡AdapterRustGo設計模式APT