1 類適配器模式:
類的適配器模式把適配的類的API轉換成為目標類的API。
在上圖中可以看出,Adaptee類并沒有sampleOperation2()方法,而客戶端則期待這個方法。為使客戶端能夠使用Adaptee類,提供一個中間環(huán)節(jié),即類Adapter,把Adaptee的API與Target類的API銜接起來。Adapter與Adaptee是繼承關系,這決定了這個適配器模式是類的:
public interface Target {
public void method1();
public void method2();
}
public class Adaptee {
public void method1(){
System.out.println("method1 from Adaptee");
}
}
public class AdapterTestClass extends Adaptee implements Target{
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("method2 implements target interface");
}
public static void main(String[] args) {
AdapterTestClass testClass = new AdapterTestClass();
testClass.method1();
testClass.method2();
}
}
2 對象適配器模式
與類的適配器模式一樣,對象的適配器模式把被適配的類的API轉換成為目標類的API,與類的適配器模式不同的是,對象的適配器模式不是使用繼承關系連接到Adaptee類,而是使用委派關系連接到Adaptee類。
(既不繼承Adaptee 也不實現接口target)
public class AdapterTestClass2 {
private Adaptee adaptee;
public AdapterTestClass2(Adaptee tee){
this.adaptee = tee;
}
public void method1(){
this.adaptee.method1();
}
public void method2(){
System.out.println("method2 in AdapterTestClass2~");
}
public static void main(String[] args) {
new AdapterTestClass2(new Adaptee()).method1();
new AdapterTestClass2(new Adaptee()).method2();
}
}
類適配器和對象適配器的權衡
●類適配器使用對象繼承的方式,是靜態(tài)的定義方式;而對象適配器使用對象組合的方式,是動態(tài)組合的方式。
●對于類適配器,由于適配器直接繼承了Adaptee,使得適配器不能和Adaptee的子類一起工作,因為繼承是靜態(tài)的關系,當適配器繼承了Adaptee后,就不可能再去處理? Adaptee的子類了。
對于對象適配器,一個適配器可以把多種不同的源適配到同一個目標。換言之,同一個適配器可以把源類和它的子類都適配到目標接口。因為對象適配器采用的是對象組合的關系,只要對象類型正確,是不是子類都無所謂。
●對于類適配器,適配器可以重定義Adaptee的部分行為,相當于子類覆蓋父類的部分實現方法。
對于對象適配器,要重定義Adaptee的行為比較困難,這種情況下,需要定義Adaptee的子類來實現重定義,然后讓適配器組合子類。雖然重定義Adaptee的行為比較困難,但是想要增加一些新的行為則方便的很,而且新增加的行為可同時適用于所有的源。
●對于類適配器,僅僅引入了一個對象,并不需要額外的引用來間接得到Adaptee。
對于對象適配器,需要額外的引用來間接得到Adaptee。
建議盡量使用對象適配器的實現方式,多用合成/聚合、少用繼承。當然,具體問題具體分析,根據需要來選用實現方式,最適合的才是最好的。
適配器模式的優(yōu)點
更好的復用性
系統(tǒng)需要使用現有的類,而此類的接口不符合系統(tǒng)的需要。那么通過適配器模式就可以讓這些功能得到更好的復用。
更好的擴展性
在實現適配器功能的時候,可以調用自己開發(fā)的功能,從而自然地擴展系統(tǒng)的功能。
適配器模式的缺點
過多的使用適配器,會讓系統(tǒng)非常零亂,不易整體進行把握。比如,明明看到調用的是A接口,其實內部被適配成了B接口的實現,一個系統(tǒng)如果太多出現這種情況,無異于一場災難。因此如果不是很有必要,可以不使用適配器,而是直接對系統(tǒng)進行重構。
3 缺省適配模式
缺省適配(Default Adapter)模式為一個接口提供缺省實現,這樣子類型可以從這個缺省實現進行擴展,而不必從原有接口進行擴展。作為適配器模式的一個特例,缺省是適配模式在JAVA語言中有著特殊的應用。
缺省適配模式是一種“平庸”化的適配器模式。(實現類不必實現接口所有方法或留空的方法,可以有選擇性了)
public interface DefaultImp {
public? void m1();
public? void m2();
public? void m3();
public? void m4();
public? void m5();
public? void mustBeImp();
}
public abstract class? AbstractDefautImp implements DefaultImp {
/* 可以只 些部分方法*/
public? void m1(){};
public? void m2(){};
public? void m3(){};
public? void m4(){};
public? void m5(){};
public void mustBeImp() {
System.out.println("mustBeImp method in AbstractDefautImp");
}
}
public class AdapterTestClass3 extends AbstractDefautImp{
/*** (實現類不必實現接口所有方法或留空的方法,可以有選擇性了)***/
@Override
public void m1() {System.out.println("m1 Override in Adaptertestclass3");};
public static void main(String[] args) {
AdapterTestClass3 test? = new AdapterTestClass3();
test.m1();
test.mustBeImp();
}
}