假如咱們又這樣軟件系統,咱們但願它可以和一個新的庫搭配使用,可是這個庫所提供的接口與咱們的軟件系統不兼容,咱們不想改變現有代碼就能解決這個問題,怎麼辦?這個時候咱們就須要將這個新的庫接口轉換成咱們所須要的接口,這就是適配器模式設計動機。java
1、模式定義 編程
何謂適配器模式?適配器模式就是將一個類的接口,轉換成客戶指望的另外一個接口。適配器讓本來接口不兼容的類能夠合做無間。編程語言
在適配器模式中,咱們能夠定義一個包裝類,包裝不兼容接口的對象,這個包裝類就是適配器,它所包裝的對象就是適配者。this
適配器提供給客戶須要的接口,適配器的實現就是將客戶的請求轉換成對適配者的相應的接口的引用。也就是說,當客戶調用適配器的方法時,適配器方法內部將調用適配者的方法,客戶並非直接訪問適配者的,而是經過調用適配器方法訪問適配者。由於適配器可使互不兼容的類可以「合做愉快」。spa
2、模式結構 .net
這個適配器模式充滿着良好的OO設計原則:使用對象組合,以修改的接口包裝別適配者。並且這樣作還有一個優勢,被適配者的任何子類,均可以搭配適配器使用。設計
適配器模式有以下四個角色:orm
Target:目標抽象類對象
Adapter:適配器類blog
Adaptee:適配者類
Client:客戶類
3、模式實現
在這裏咱們模擬一個機器人。首先咱們擁有一個機器人,它能夠叫(cry),跑(run)。如今咱們但願它可以像小狗同樣叫,像小狗同樣跑。
首先咱們須要一個機器人接口:Robot.java。提供cry()和run()方法。
[java] view plaincopyprint?
public interface Robot {
void cry();
void move();
}
而後是小狗:Dog.java。能夠旺旺叫和快快跑。
[java] view plaincopyprint?
public class Dog {
public void wang(){
System.out.println("小狗叫:汪汪.....");
}
public void run(){
System.out.println("小狗快快跑......");
}
}
輪到重點啦:適配器,這個適配器可以使仿生機器人像狗同樣叫,同樣跑。
[java] view plaincopyprint?
public class DogAdapter implements Robot{
Dog dog;
public DogAdapter(Dog dog){ //取得要適配的對象的引用
this.dog = dog;
}
/**
* 實現接口中的方法,只須要在相應的方法間進行轉換便可完成。
*/
public void cry() {
System.out.println("機器人模擬狗叫...");
dog.wang();
}
public void move() {
System.out.println("機器人模擬狗跑...");
dog.run();
}
}
客戶端:Client.java
[java] view plaincopyprint?
public class Client {
public static void main(String[] args) {
BioRobot robot = new BioRobot(); //首先咱們須要一個機器人
Dog dog = new Dog(); //和一隻狗
//將這隻狗包裝到機器人中,使其有點兒像機器人
Robot dogRobot = new DogAdapter(dog);
//而後是機器人叫和跑
System.out.println("BioRob cry.....");
dogRobot.cry();
dogRobot.move();
}
}
運行結果。
若是咱們但願這個仿生機器人可以像鳥同樣唧唧的叫和飛呢?只須要添加一個可以叫和飛的鳥類以及一個鳥的適配器便可。以下:
[java] view plaincopyprint?
public class Bird {
public void jiji(){
System.out.println("唧唧..........");
}
public void fly(){
System.out.println("我在飛........");
}
}
[java] view plaincopyprint?
public class BirdAdapter implements Robot{
Bird bird;
public BirdAdapter(Bird bird){
this.bird = bird;
}
public void cry() {
bird.jiji();
}
public void move() {
bird.fly();
}
}
4、模式優缺點
優勢
1. 將目標類和適配者類解耦,經過使用適配器讓不兼容的接口變成了兼容,讓客戶從實現的接口解耦。
2. 增長了類的透明性和複用性,將具體的實現封裝在適配者類中,對於客戶端類來講是透明的,並且提升了適配者的複用性。
3. 靈活性和擴展性都很是好在不修改原有代碼的基礎上增長新的適配器類,符合「開閉原則」。
5、使用場景
1. 系統須要使用現有的類,而這些類的接口不符合系統的須要。
2.想要創建一個能夠重複使用的類,用於與一些彼此之間沒有太大關聯的一些類
6、模式擴充
適配器模式分爲對象適配器和類適配器。前面所概述的是對象適配器。爲何沒有將類適配器呢?由於類適配器須要使用多重繼承,這個在java中沒有辦法實現的。可是當咱們遇到可使用多重繼承語言的時候,仍是可能會遇到這種需求。
類適配器模式UML圖。
在類適配器中,因爲適配器是適配者的子類,因此能夠在適配器類中置換一些適配者的方法,使得適配器的靈活性更強。可是對於一些不支持多重繼承的編程語言來講(Java ,C#),其使用就會存在必定的侷限性:不能將一個適配者類和它的子類都適配到目標接口。
對於對象適配器而言,一個對象適配器能夠把多個不一樣的適配者適配到同一個目標,也就是說,同一個適配器能夠把適配者類和它的子類都適配到目標接口。可是若是咱們須要置換掉適配者的某些方法時,這個實現就會比較難,咱們首先要先作一個適配者的子類,將適配者類的方法置換掉,而後再把適配者類的子類當作真正的適配者進行適配,實現過程較爲複雜。
7、模式總結
一、當咱們須要使用的一個現有的類,可是他的接口並不符合咱們的需求時,咱們可使用適配器模式。
二、適配器模式分爲類適配器和對象適配器,其中類適配器須要用到多重繼承。