定義
適配器模式(adapter pattern)將一個類的接口,轉換成客戶期望的另外一個接口。適配器讓原本不兼容的類可以合作無間。
上圖清晰地表述了適配器模式的威力,通過創建適配器接口,現有的系統可以不用修改代碼就可以通過適配器接口調用廠商類,現有的系統和廠商類之間可以很好地協作。
適配器模式讓不兼容的接口變成兼容,還可以讓客戶從廠商類的實現中解耦,當廠商類改變時,適配可以封裝變化,客戶代碼不需要跟着變化。
適配器模式分爲兩種:對象適配器和類適配器。從上面的類圖可以看出,對象適配器利用組合的方式將請求傳送給被適配器。類適配器使用了多重繼承,同時繼承了Target和Adaptee類。
代碼實現
下面以JDK中的例子來說明適配器模式。
JDK 1.0的集合(collection)類型(例如: Vector,Stack,Hashtable)都實現了一個名爲elements()的方法,該方法返回一個Enumeration。Enumeration的定義如下:
public interface Enumeration<E> {
boolean hasMoreElements();
E nextElement();
}
JDK 1.2引入了Iterator接口:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
}
在面對遺留代碼,這些代碼暴露出Enumeration接口,但是我們又希望在新的代碼中只使用Iterator接口。想解決這個問題,我們需要構造一個適配器,將Enumeration適配到Iterator:
import java.util.*;
public class EnumerationIterator implements Iterator {
Enumeration enumeration;
public EnumerationIterator(Enumeration enumeration) {
this.enumeration = enumeration;
}
public boolean hasNext() {
return enumeration.hasMoreElements();
}
public Object next() {
return enumeration.nextElement();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
客戶代碼:
import java.util.*;
public class EnumerationIteratorTestDrive {
public static void main (String args[]) {
Vector v = new Vector(Arrays.asList(args));
// iterator是實現了Iterator接口的適配器
Iterator iterator = new EnumerationIterator(v.elements());
// 客戶代碼只要調用Iterator的接口API接口,不用關心適配器的實現
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
該模式體現了哪些OO原則
-
在對象適配器中,client針對接口編程。
在類適配器中,client針對子類Target編程,不針對具體的實現Adapter編程。 -
在對象適配器中,適配器使用對象組合的方式,委託給被適配器。
本章總結
適配器模式和裝飾者模式的區別:
適配器模式強調的是對接口的轉換,讓原來不兼容的接口變成兼容的。裝飾者模式則強調通過對對象的封裝來增強原對象的功能,所以裝飾者一定會在原對象的基礎上增加新的功能,而適配器模式重點在接口轉換,不一定會增加新的功能
適配器模式和外觀模式的差別:
兩種模式都是對其它的接口的再次封裝。差別在適配器強調對一個或者多個接口的轉換,而外觀模式則強調簡化接口