設計模式學習筆記之介面卡模式

birdlove1987發表於2017-03-04

什麼是介面卡模式?

介面卡模式(有時候也稱包裝樣式或者包裝)就是將一個類的介面適配成使用者所期待的。一個適配允許通常因為介面不相容而不能在一起工作的類工作在一起,做法是將類自己的介面包裹在一個已存在的類中。

看一個我們日常生活中的圖:




如果出國旅行,肯定會買一些國外的優質的電器回來,但是國外的電器插頭可能是這樣的。。

而國內的插座確實這樣的。。




肯定是插不進去的。。怎麼辦呢?神通廣大的介面卡就該出場了!




這下應該可以理解介面卡是用來幹嘛的了吧,其實設計模式中的介面卡模式和這個道理是一樣的。

我們來看一下介面卡模式的類圖




PS:我畫的可能有點醜。。

介面卡主要的作用就是將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。

下面我們來舉一個具體的例子說明一下吧:

《暮光之城》裡的吸血鬼家族,今天晚上要舉辦一場吸血鬼舞會,一名人類戰士吸血鬼研究學者得到訊息也想混進去趁機研究一下吸血鬼,但是如果他直接去,那肯定就被吸血鬼們發現了,所以他要偽裝一下,下面我們用程式碼來實現一下




人類介面


//人類介面
public interface Human {
	//進食
	public void eat();
	//運動
	public void run();
}


人類戰士類


public class Soldier implements Human {

	@Override
	public void eat(){
		// TODO Auto-generated method stub
		System.out.println("吃飯");
	}

	@Override
	public void run(){
		// TODO Auto-generated method stub
		System.out.println("跑得很慢");
	}
}


PS:這裡跑得慢,肯定是跟吸血鬼們比較的,這哥們在人類中肯定是精英。


吸血鬼介面


//吸血鬼介面
public interface Vampire {
	//進食
	public void suckBlood();
	//運動
	public void run();
}

吸血鬼戰士類


public class VampireWarriors implements Vampire {

	@Override
	public void suckBlood() {
		// TODO Auto-generated method stub
		System.out.println("吸血");
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("跑得很快");
	}
}

好了下面我們就要對這位人類戰士進行一下化妝了

其實在介面卡模式中,適配有兩種方法


物件介面卡模式
-- 在這種介面卡模式中,介面卡容納一個它包裹的類的例項。在這種情況下,介面卡呼叫被包裹物件的物理實體。
類介面卡模式
-- 這種介面卡模式下,介面卡繼承自已實現的類(一般多重繼承 ps:java中可以通過介面多繼承)。


我們先來實現一下:

物件介面卡模式:


//物件適配模式
public class SoldierAdapter implements Vampire {
	
	//被適配的士兵類
	private Soldier soldier;
	
    //在建構函式中傳入士兵類
	public SoldierAdapter(Soldier soldier)
	{
		this.soldier=soldier;
	}
	
	//偽裝吸血鬼進食
	@Override
	public void suckBlood() {
		// TODO Auto-generated method stub
		soldier.eat();
		System.out.println("飯的內容就是血");
	}
	
	//偽裝吸血鬼運動,因為跑得慢所以要多跑幾次
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<5;i++)
		{
			soldier.run();
		}
	}
}


測試一下:

測試類


public class MainTest {
	public static void main(String[] args) {
		
		//人類戰士
		Soldier soldier=new Soldier();
		
		//吸血鬼戰士
		VampireWarriors vampireWarriors=new VampireWarriors();
		
		//偽裝的吸血鬼戰士
		Vampire vampire2humanAdapter=new SoldierAdapter(soldier);
		
		//人類戰士行為
		System.out.println("人類戰士:");
		soldier.eat();
		soldier.run();
		
		System.out.println();
		
		//吸血鬼戰士行為
		System.out.println("吸血鬼戰士:");
		vampireWarriors.suckBlood();
		vampireWarriors.run();
		
		System.out.println();
		
		//偽裝者的行為
		System.out.println("人類戰士冒充吸血鬼戰士:");
		vampire2humanAdapter.suckBlood();
		vampire2humanAdapter.run();	
	}
}




還不錯,但願吸血鬼發現不了這個兄弟。。


下面我們來實現一下類介面卡模式


//類介面卡模式
public class SoldierAdapter2 extends Soldier implements Vampire {
	
	//偽裝吸血鬼的行為
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<5;i++)
		{
			super.run();
		}
	}

	@Override
	public void suckBlood() {
		// TODO Auto-generated method stub
		super.eat();
		System.out.println("飯的內容就是血");
	}
}

測試一下


public class MainTest {
	public static void main(String[] args) {
		
		//人類戰士
		Soldier soldier=new Soldier();
		
		//吸血鬼戰士
		VampireWarriors vampireWarriors=new VampireWarriors();
		
		//偽裝的吸血鬼戰士
		Vampire vampire2humanAdapter=new SoldierAdapter2();//這裡就不用傳入物件了
		
		//人類戰士行為
		System.out.println("人類戰士:");
		soldier.eat();
		soldier.run();
		
		System.out.println();
		
		//吸血鬼戰士行為
		System.out.println("吸血鬼戰士:");
		vampireWarriors.suckBlood();
		vampireWarriors.run();
		
		System.out.println();
		
		//偽裝者的行為
		System.out.println("人類戰士冒充吸血鬼戰士:");
		vampire2humanAdapter.suckBlood();
		vampire2humanAdapter.run();	
	}
}




結果是一樣的啦


我們比較一下物件介面卡是類介面卡:


類介面卡:
由於介面卡類是適配者類的子類,因此可以再介面卡類中置換一些適配者的方法,使得介面卡的靈活性更強。但是對於Java、C#等不支援多重繼承的語言,一次最多隻能適配一個適配者類,而且目標抽象類只能為介面,不能為類,其使用有一定的侷限性,不能將一個適配者類和他的子類同時適配到目標介面。


物件介面卡:
把多個不同的適配者適配到同一個目標,也就是說,同一個介面卡可以把適配者類和他的子類都適配到目標介面。但是,與類介面卡模式相比,要想置換適配者類的方法就不容易。


再來看看介面卡模式的優點是 場景

1、將目標類和適配者類解耦
2、增加了類的透明性和複用性,將具體的實現封裝在適配者類中,對於客戶端類來說是透明的,而且提高了適配者的複用性
3、靈活性和擴充套件性都非常好,符合開閉原則


介面卡模式的適用場景: 
1、我們在使用第三方的類庫,或者說第三方的API的時候,我們通過介面卡轉換來滿足現有系統的使用需求
2、我們的舊系統與新系統進行整合的時候,我們發現舊系統的資料無法滿足新系統的需求,那麼這個時候,我們可能需要介面卡,完成呼叫需求。













相關文章