天天看點

一個示例讓你明白擴充卡模式現實生活中的擴充卡實作電源擴充卡總結

大家好,又見面了,我是你們的朋友全棧君。

現實生活中的擴充卡

本文讨論擴充卡模式。擴充卡模式是23中設計模式之一,它的主要作用是在新接口和老接口之間進行适配。它非常像我們出國旅行時帶的電源轉換器。為了舉這個例子,我還特意去京東上搜了一下電源轉換器,确實看到了很多地方的标準不一樣。我們國家的電器使用普通的扁平兩項或三項插頭,而去外國的話,使用的标準就不一樣了,比如德國,使用的是德國标準,是兩項圓頭的插頭。如果去德國旅遊,那麼我們使用的手機充電器插頭無法插到德國的插排中去,那就意味着我們無法給手機充電。怎樣解決這個問題呢?隻要使用一個電源轉化器就行了。如下圖所示:

一個示例讓你明白擴充卡模式現實生活中的擴充卡實作電源擴充卡總結

該擴充卡下面的插頭符合德國标準,可以插到德國的插排中去,上面提供的接口符合國标,可以供我們的手機充電器使用。

實作電源擴充卡

下面我們使用代碼來表述擴充卡模式:

代碼中有兩個接口,分别為德标接口和國标接口,分别命名為DBSocketInterface和GBSocketInterface,此外還有兩個實作類,分别為德國插座和中國插座,分别為DBSocket和GBSocket。為了提供兩套接口之間的适配,我們提供了一個擴充卡,叫做SocketAdapter。除此之外,還有一個用戶端,比如是我們去德國旅遊時住的一家飯店,叫Hotel,在這個德國旅館中使用德國接口。

德标接口:

/**
 * 德标接口
 */
public interface DBSocketInterface {
	
	/**
	 * 這個方法的名字叫做:使用兩項圓頭的插口供電
	 * 本人英語就這個水準
	 */
	void powerWithTwoRound();
}           

複制

德國插座實作德标接口

/**
 * 德國插座
 */
public class DBSocket implements DBSocketInterface{
	
	public void powerWithTwoRound(){
		System.out.println("使用兩項圓頭的插孔供電");
	}
}           

複制

德國旅館是一個用戶端,它裡面有德标的接口,可以使用這個德标接口給手機充電:

/** * 德國飯店 */public class Hotel {	//旅館中有一個德标的插口	private DBSocketInterface dbSocket;		public Hotel(){}		public Hotel(DBSocketInterface dbSocket) {		this.dbSocket = dbSocket;	}	public void setSocket (DBSocketInterface dbSocket){		this.dbSocket = dbSocket;	}	//旅館中有一個充電的功能	public void charge(){				//使用德标插口充電		dbSocket.powerWithTwoRound();	}}           

複制

現在寫一段代碼進行測試:

public class Test {

	public static void main(String[] args) {
		
		//初始化一個德國插座對象, 用一個德标接口引用它
		DBSocketInterface dbSoket = new DBSocket();
		
		//建立一個旅館對象
		Hotel hotel = new Hotel(dbSoket);
		
		//在旅館中給手機充電
		hotel.charge();
	}
}           

複制

運作程式,列印出以下結果: 使用兩項圓頭的插孔供電

現在我去德國旅遊,帶去的三項扁頭的手機充電器。如果沒有帶電源擴充卡,我是不能充電的,因為不可能為了我一個旅客而為我更改牆上的插座,更不可能為我專門蓋一座使用中國國标插座的飯店。因為人家德國人一直這麼使用,并且用的挺好,俗話說入鄉随俗,我就要自己想辦法來解決問題。對應到我們的代碼中,也就是說,上面的Hotel類,DBSocket類,DBSocketInterface接口都是不可變的(由德國的客戶提供),如果我想使用這一套API,那麼隻能自己寫代碼解決。

下面是國标接口和中國插座的代碼。

國标接口:

/**
 * 國标接口
 */
public interface GBSocketInterface {
	
	/**
	 * 這個方法的名字叫做:使用三項扁頭的插口供電
	 * 本人英語就這個水準,從有道詞典查得, flat意思好像是: 扁的
	 */
	void powerWithThreeFlat();
}           

複制

中國插座實作國标接口:

/**
 * 中國插座
 */
public class GBSocket implements GBSocketInterface{
	
	@Override
	public void powerWithThreeFlat() {
		System.out.println("使用三項扁頭插孔供電");
	}
}           

複制

可以認為這兩個東西是我帶到德國去的,目前他們還不能使用,因為接口不一樣。那麼我必須建立一個擴充卡,這個擴充卡必須滿足以下條件:

1 必須符合德國标準的接口,否則的話還是沒辦法插到德國插座中;

2 在調用上面實作的德标接口進行充電時,提供一種機制,将這個調用轉到對國标接口的調用 。

這就要求:

1 擴充卡必須實作原有的舊的接口

2 擴充卡對象中持有對新接口的引用,當調用舊接口時,将這個調用委托給實作新接口的對象來處理,也就是在擴充卡對象中組合一個新接口。

下面給出擴充卡類的實作:

public class SocketAdapter  
		implements DBSocketInterface{   //實作舊接口

	//組合新接口
	private GBSocketInterface gbSocket;
	
	/**
	 * 在建立擴充卡對象時,必須傳入一個新街口的實作類
	 * @param gbSocket
	 */
	public SocketAdapter(GBSocketInterface gbSocket) {
		this.gbSocket = gbSocket;
	}

	
	/**
	 * 将對就接口的調用适配到新接口
	 */
	@Override
	public void powerWithTwoRound() {
		
		gbSocket.powerWithThreeFlat();
	}

}           

複制

這個擴充卡類滿足了上面的兩個要求。下面寫一段測試代碼來驗證一下擴充卡能不能工作,我們按步驟一步步的寫出代碼,以清楚的說明擴充卡是如何使用的。

1 我去德國旅遊,帶去的充電器是國标的(可以将這裡的GBSocket看成是充電器)

GBSocketInterface gbSocket = new GBSocket();           

複制

2 來到德國後, 找到一家德國飯店住下 (這個飯店還是上面代碼中的飯店,使用的依然是德國标準的插口)

Hotel hotel = new Hotel();           

複制

3 由于沒法充電,我拿出随身帶去的擴充卡,并且将我帶來的充電器插在擴充卡的上端插孔中。這個上端插孔是符合國标的,我的充電器完全可以插進去。

SocketAdapter socketAdapter = new SocketAdapter(gbSocket);           

複制

4 再将擴充卡的下端插入飯店裡的插座上

hotel.setSocket(socketAdapter);           

複制

5 可以在飯店中使用擴充卡進行充電了

hotel.charge();           

複制

上面的五個步驟就是擴充卡的使用過程,下面是完整的測試代碼。

public class TestAdapter {

	public static void main(String[] args) {
		
		GBSocketInterface gbSocket = new GBSocket();
		
		Hotel hotel = new Hotel();
		
		SocketAdapter socketAdapter = new SocketAdapter(gbSocket);
		
		hotel.setSocket(socketAdapter);
		
		hotel.charge();
	}
}           

複制

運作上面的程式,列印出以下結果:

使用三項扁頭插孔供電

這說明擴充卡起作用了,上一個執行個體中列印的是:使用兩項圓頭的插孔供電。 現在可以使用三項扁頭插孔供電了。我們并沒有改變飯店中的德标插口,提供了一個擴充卡就能使用國标的插口充電。這就是擴充卡模式的魅力:不改變原有接口,卻還能使用新接口的功能。

由于上面的代碼都是分片的,沒有完整的項目源碼,為了使讀者對示例中的類和接口更清晰,下面給出UML類圖:

一個示例讓你明白擴充卡模式現實生活中的擴充卡實作電源擴充卡總結

總結

根據上面的示例,想必讀者應該能比較深入的了解到了擴充卡模式的魔力。下面給出擴充卡模式的定義(該定義來自于《Head First 設計模式》):

擴充卡模式将一個類的接口轉換成客戶期望的另一個接口,讓原本不相容的接口可以合作無間。

下面給出擴充卡模式的類圖(該類圖同樣來自于《Head First 設計模式》):

一個示例讓你明白擴充卡模式現實生活中的擴充卡實作電源擴充卡總結

擴充卡模式的三個特點:

1 擴充卡對象實作原有接口

2 擴充卡對象組合一個實作新接口的對象(這個對象也可以不實作一個接口,隻是一個單純的對象)

3 對擴充卡原有接口方法的調用被委托給新接口的執行個體的特定方法

有人認為講解設計模式的例子都太簡單,看着感覺是那麼回事,但是要是真想在項目開發中使用,還真是應用不到。其實我們不必在項目中刻意使用設計模式,而是應該從實際的設計問題出發,看哪個模式能解決我們的問題,就使用哪個模式。不要為了使用模式而使用模式,那樣就舍本逐末了,一般情況下,隻要遵循一定的設計原則就可以了,設計模式也是根據這些原則被總結出來的,熟悉了這些原則,模式自然而然就有了。

其實隻要平時善于思考了感悟,在項目中是可以用到設計模式的,并且如果用的合理的話,會為此而受益良多。在下一篇部落格中,我會以項目中遇到的一個真實的需求來解析擴充卡模式的使用,敬請期待。

關于上面提到的擴充卡模式實際應用的文章已經完成并發表, 感興趣的朋友可以看一下, 如果有不合理的地方還請指正。

文章連結 運用擴充卡模式應對項目中的變化

釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/160012.html原文連結:https://javaforall.cn