類適配器
客戶的開發(fā)人員定義了一個(gè)接口,期望用這個(gè)接口來完成整數(shù)的求和操作,接口定義如下:
- public interface Operation{
- public int add(int a,int b);
- }
public interface Operation{
public int add(int a,int b);
}
開發(fā)人員在了解這個(gè)接口的定義后,發(fā)現(xiàn)一個(gè)第三方類,里面有一個(gè)方法能實(shí)現(xiàn)他們期望的功能,其代碼如下:
- public class OtherOperation{
- public int otherAdd(int a,int b){
- return a + b;
- }
- }
public class OtherOperation{
public int otherAdd(int a,int b){
return a + b;
}
}
以上第三方類
OtherOperation的方法
public int otherAdd(int a,int b)所提供的功能,完全能符合客戶的期望,所以只需要想辦法把
OtherOperation的
otherAdd(int a,int b)和客戶的
Operation接口聯(lián)系起來,讓這個(gè)第三方類來為客戶提供他們期望的服務(wù)就行了,這樣就避免了開發(fā)人員再度去研究類似
OtherOperation的
otherAdd(int a,int b)方法的實(shí)現(xiàn)(利用已有的輪子,避免重復(fù)發(fā)明),這方法之一,就是用適配器模式:
- public class AdapterOperation extends OtherOperation implements Operation{
- public int add(int a,int b){
- return otherAdd(a,b);
- }
- }
public class AdapterOperation extends OtherOperation implements Operation{
public int add(int a,int b){
return otherAdd(a,b);
}
}
以上就是適配器的實(shí)現(xiàn)方法之一,
類適配器,在以上實(shí)現(xiàn)中存在著三中角色分別是:
1:適配目標(biāo)角色:Operation。
2:適配類(原)角色:OtherOperation。
3:適配器角色:AdapterOperation。
其中適配器角色是適配器模式的核心。
適配器的主要工作就是通過封裝現(xiàn)有的功能,使他滿足需要的接口。
對(duì)象適配器
我們?cè)賮砜纯戳硪环N情況:
假如客戶接口期望的功能不止一個(gè),而是多個(gè):
- public interface Operation{
- public int add(int a,int b);
- public int minus(int a,int b);
- public int multiplied(int a,int b);
- }
public interface Operation{
public int add(int a,int b);
public int minus(int a,int b);
public int multiplied(int a,int b);
}
而能提供這些實(shí)現(xiàn)的原可能不止一個(gè):
- public class OtherAdd{
- public int otherAdd(int a,int b){
- return a + b;
- }
- }
-
- public class OtherMinus{
- public int minus(int a,int b){
- return a - b;
- }
- }
-
- public class OtherMultiplied{
- public int multiplied(int a,int b){
- return a * b;
- }
- }
public class OtherAdd{
public int otherAdd(int a,int b){
return a + b;
}
}
public class OtherMinus{
public int minus(int a,int b){
return a - b;
}
}
public class OtherMultiplied{
public int multiplied(int a,int b){
return a * b;
}
}
由于java是不能實(shí)現(xiàn)多繼承的,所以我們不能通過構(gòu)建一個(gè)適配器,讓他來繼承所有原以完成我們的期望,這時(shí)候怎么辦呢?只能用適配器的另一種實(shí)現(xiàn)--
對(duì)象適配器:
- public class AdapterOperation implements Operation{
- private OtherAdd add;
- private OtherMinus minus;
- private OtherMultiplied multiplied;
-
- public void setAdd(OtherAdd add){
- this.add = add;
- }
-
- public void setMinus(OtherMinus minus){
- this.minus = minus;
- }
-
- public void setMultiplied(OtherMultiplied multiplied){
- this.multiplied = multiplied;
- }
-
-
- public int add(int a,int b){
- return add.otherAdd(a,b);
- }
-
-
- public int minus(int a,int b){
- return minus.minus(a,b);
- }
-
-
- public int multiplied(int a,int b){
- return multiplied.multiplied(a,b);
- }
- }
public class AdapterOperation implements Operation{
private OtherAdd add;
private OtherMinus minus;
private OtherMultiplied multiplied;
public void setAdd(OtherAdd add){
this.add = add;
}
public void setMinus(OtherMinus minus){
this.minus = minus;
}
public void setMultiplied(OtherMultiplied multiplied){
this.multiplied = multiplied;
}
//適配加法運(yùn)算
public int add(int a,int b){
return add.otherAdd(a,b);
}
//適配減法運(yùn)算
public int minus(int a,int b){
return minus.minus(a,b);
}
//適配乘法運(yùn)算
public int multiplied(int a,int b){
return multiplied.multiplied(a,b);
}
}
上面代碼很明顯,適配器并不是通過繼承來獲取
適配類(原)的功能的,而是通過
適配類的對(duì)象來獲取的,這就解決了java不能多繼承所帶來的不便了。這也是java提倡的編程思想之一,即
盡量使用聚合不要使用繼承。
還有一種情況是需要使用
對(duì)象適配器的。我們來看看,
單我們的客戶提供的需求并不是一個(gè)明確的接口,而是一個(gè)類,并沒有定義期望的方法,如下
- public class A{
- public int add(int a,int b){
- return a + b;
- }
- }
public class A{
public int add(int a,int b){
return a + b;
}
}
現(xiàn)在客戶要一個(gè)新類B,要求能在保留類A功能的情況下增加一個(gè)運(yùn)算減法的功能,并要求B能隨時(shí)替換掉A但不能對(duì)已有系統(tǒng)造成影響。這樣我們只能新建一個(gè)類B,并讓B繼承A。
- public class B extends A{
- b(){
- super();
- }
-
- public int minus(int a,int b){
-
- }
- }
public class B extends A{
b(){
super();
}
public int minus(int a,int b){
//待實(shí)現(xiàn)的減法運(yùn)算函數(shù)..
}
}
這時(shí)候,我們發(fā)現(xiàn)類C已經(jīng)提供了實(shí)現(xiàn)減法的函數(shù),
- public class C{
- public int minus(int a,int b){
- return a - b;
- }
- }
public class C{
public int minus(int a,int b){
return a - b;
}
}
為了避免重復(fù)去設(shè)計(jì)該函數(shù),我們決定引入C類,通過適配C類來達(dá)到我們的期望,但問題是A和C都是一個(gè)具體類,我們無法讓B同時(shí)繼承這個(gè)兩個(gè)類,而B繼承A又是必須的,所以我們只能考慮把C給內(nèi)聚到B內(nèi)部,
對(duì)象適配器又得派上用場(chǎng)了。
- public class B extends A{
-
- private C c;
-
- B(){
- super();
- }
-
- public void setMinus(C c){
- this.c= c;
- }
-
- public int minus(int a,int b){
- return c.minus(a,b);
- }
- }
public class B extends A{
private C c;
B(){
super();
}
public void setMinus(C c){
this.c= c;
}
public int minus(int a,int b){
return c.minus(a,b);
}
}
這樣,在需要A類的地方都能用B類來代替,同時(shí)又保證了新的功能的引入。
更靈活的實(shí)現(xiàn)--隱藏目標(biāo)接口的抽象適配器
做java 桌面應(yīng)用的都知道WindowListener接口,
- public interface WindowListener extends EventListener{
- public void windowActivated(WindowEvent e);
- public void windowClosed(WindowEvent e);
- public void windowClosing(WindowEvent e);
- public void windowDeactivated(WindowEvent e);
- public void windowDeiconified(WindowEvent e);
- public void windowIconified(WindowEvent e);
- public void windowOpened(WindowEvent e);
- }
public interface WindowListener extends EventListener{
public void windowActivated(WindowEvent e);
public void windowClosed(WindowEvent e);
public void windowClosing(WindowEvent e);
public void windowDeactivated(WindowEvent e);
public void windowDeiconified(WindowEvent e);
public void windowIconified(WindowEvent e);
public void windowOpened(WindowEvent e);
}
要實(shí)現(xiàn)這個(gè)接口,我們就必須實(shí)現(xiàn)它所定義的所有方法,但是實(shí)際上,我們很少需要同時(shí)用到所有的方法,我們要的只是其中的兩三個(gè)。為了不使我們實(shí)現(xiàn)多余的方法,
jdk WindowListener提供了一個(gè)WindowListener的默認(rèn)實(shí)現(xiàn)類WindowAdapter類,這是一個(gè)抽象類,
- public abstract class WindowAdapter implements WindowListener{
- public void windowActivated(WindowEvent e){}
- public void windowClosed(WindowEvent e){}
- public void windowClosing(WindowEvent e){}
- public void windowDeactivated(WindowEvent e){}
- public void windowDeiconified(WindowEvent e){}
- public void windowIconified(WindowEvent e){}
- public void windowOpened(WindowEvent e){}
- }