設計模式(八):適配器模式


一、概述

  適配器模式將一個類的接口,轉換為客戶期望的另一個接口。適配器讓原本不兼容的類可以合作無間

二、解決問題

  從模式的定義中,我們看到適配器模式就是用來轉換接口,解決不兼容問題的。想想我們現實生活中的適配器,最常用的就是手機充電器了,也叫做電源適配器,它把家用交流強電轉換為手機用的直流弱電。其中交流電就是被適配者,充電器是適配器,手機是用電客戶。

三、結構類圖

  

四、成員角色

  客戶(Client):只能調用目標接口功能,不能直接使用被適配器,但可以通過適配器的接口轉換間接使用被適配器。

  目標接口(Target):客戶看到的接口,適配器必須實現該接口才能被客戶使用。

  適配器(Adapter):適配器把被適配者接口轉換為目標接口,提供給客戶使用。

  被適配者(Adaptee):被適配者接口與目標接口不兼容,需要適配器轉換成目標接口子類,才能被客戶使用。

五、應用實例

  下面用鳥叫和鳥飛的例子解析適配器模式,鸚鵡會叫也會飛,但鵝就只會叫不會飛,而且鵝也不是鳥類,我們要創建一個適配器,把鵝轉換成鳥。

  第一步、創建鳥接口,對應角色目標接口

package adapter.pattern;

//鳥接口
public interface Bird {
	//鳥叫
	public void chirp();
	//飛
	public void fly();
}

  第二步、創建鸚鵡類

package adapter.pattern;

//鸚鵡類實現鳥接口
public class Parrot implements Bird{

	public void chirp() {
		System.out.println("嗚嗚嗚");		
	}

	public void fly() {
		System.out.println("我能飛很遠很遠");		
	}

}

  第三步、創建鵝類,對應角色被適配者

package adapter.pattern;

//鵝類,不是鳥
public class Goose {
	//鵝會叫但不會飛,沒有飛的方法
	public void chirp(){
		System.out.println("嘎嘎嘎");
	}
}

  第四步、創建適配器

package adapter.pattern;

//適配器,把鵝類適配為鳥
public class GooseAdapter implements Bird{
	//組合鵝類
	Goose goose;
	public GooseAdapter(Goose goose){
		this.goose = goose;
	}
	
	public void chirp() {
		if(goose != null){
			//調用鳥叫的時候委托鵝叫
			goose.chirp();
		}
	}

	public void fly() {
		//不支持該操作,可以拋出該異常,客戶可以知道詳情
		throw new UnsupportedOperationException();
	}

}

  第五步、測試適配器

package adapter.pattern;

public class AdapterTest {
	public static void main(String[] args){
		System.out.println("-----鸚鵡會叫也會飛-----");
		Bird parrot = new Parrot();
		parrot.chirp();
		parrot.fly();
		
		System.out.println("-----鵝會叫但不會飛-----");
		Goose goose = new Goose();
		Bird gooseAdapter = new GooseAdapter(goose);
		gooseAdapter.chirp();
		gooseAdapter.fly();
		
		
	}
}

  運行結果:

  適配器在java中的例子,我們知道ArrayList類實現了迭代器(Iterator),但不支持枚舉(Enumeration),下面我們就來實現ArrayList的枚舉操作。

package adapter.pattern;

import java.util.ArrayList;
import java.util.Enumeration;

public class ItertorEnumeration implements Enumeration{
	//組合被適配者
	private ArrayList<String> list;
	//集合的計數器,判斷指針指向集合的位置
	private int index = 0;
	public ItertorEnumeration(ArrayList<String> list){
		this.list = list;
	}
	public boolean hasMoreElements() {
		if(list != null && list.size() > index){
			return true;
		}
		return false;
	}

	public Object nextElement() {
		String content = list.get(index);
		index++;
		return content;
	}
}

  

六、優點和缺點

  1、優點

  (1)、轉換接口,適配器讓不兼容的接口變成兼容。

  (2)、讓客戶和實現的接口解耦。有了適配器,客戶端每次調用不兼容的接口時,不用修改自己的代碼,只要調用適合的適配器就可以了。

  (3)、使用了對象組合設計原則。以組合的方式包裝被適配者,被適配者的任何子類都可以搭配着同一個適配器使用。

  (4)、體現了“開閉”原則。適配器模式把客戶和接口綁定起來,而不是和具體實現綁定,我們可以使用多個配適器來轉換多個后台類,也可以很容易地增加新的適配器。

  2、缺點

  (1)、每個被適配者都需要一個適配器,當適配器過多時會增加系統復雜度,降低運行時的性能。

  (2)、實現一個適配器可能需要下一番功夫,增加開發的難度。

七、使用場景

  1、當要使用的兩個類所做的事情相同或者相似,但是具有不同的接口時考慮使用配適器模式。

  2、當需要統一客戶端調用接口的代碼,而所調用的接口具有不兼容問題時使用適配器模式。這樣客戶端只有調用一個接口就行了,這樣可以更簡單、更直接、更緊湊。

八、總結

  1、適配器有對象適配器和類適配器,類適配器需要用到多重繼承。

  2、適配器就是轉換接口達到我們的需要。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM