什麼是結構性模式
結構性模式描述類和對象怎樣結合在一起成為較大的結構
結構性模式描述兩種不同的東西
類與類的實例
根據它們所描述的東西的不同
結構性模式可以分為類結構模式和實例結構模式兩種
類結構模式使用繼承(inheritance)來把類
接口等組合在一起
形成更大的結構
當一個類從父類繼承
並實現某接口時
這個新的類就把父類的結構和接口的結構結合起來
類結構模式是靜態的
一個類結構模式的典型的例子
就是類形式的變壓器模式
實例結構模式描述各種不同類型的把對象組合在一起
實現新的功能的方法
實例結構模式是動態的
一個典型的實例結構模式
就是代理人模式
代理人模式將在以後介紹
其它的例子包括後面將要介紹的復合模式
飛行重量模式
裝飾模式
以及實例形式的變壓器模式等
有一些模式會有類結構模式的形式和實例結構模式的形式兩種
成為以上兩種形式的結構模式的極好注解
本節要介紹的變壓器模式就是這樣
它有類形式和實例形式兩種
變壓器模式的介紹
變壓器模式把一個類的接口變換成客戶端所期待的另一種接口
變壓器模式使原本無法在一起工作的兩個類能夠在一起工作
如前所述
變壓器模式是關於類結構的結構性模式
因而是靜態的模式
這很象變壓器(Adapter)
變壓器把一種電壓變換成另一種電壓
當我把美國的電器拿回中國大陸去用的時候
我就面臨電壓不同的問題
美國的生活用電壓是
伏
而中國的電壓是
伏
我如果要在中國大陸使用我在美國使用的電器
我就必須有一個能把
伏電壓轉換成
伏電壓的變壓器
而這正象是本模式所做的事
因此此模式被稱為變壓器模式
讀者可能也會想到
Adapter在中文也可翻譯為轉換器(適配器)
實際上
轉換器(適配器)也是一個合適的名字
仍用電器作例子
美國的電器的插頭一般是三相的
即除了陽極
陰極外
還有一個地極
中國大陸的建築物內的電源插座一般只有兩極
沒有地極
這時候
即便電器的確可以接受
伏電壓
電源插座和插頭不匹配
也使電器無法使用
一個三相到兩相的轉換器(適配器)就能解決這個問題
因此此模式也可被稱為轉換器(適配器)模式
同時
這種做法也很象包裝過程
被包裝的物體的真實樣子被包裝所掩蓋和改變
因此有人把這種模式叫做包裝(Wrapper)模式
事實上
我們經常寫很多這樣的wrapper類
把已有的一些類包裹起來
使之能有滿足需要的接口
變壓器模式有類形式和實例形式兩種不同的形式
類形式的變壓器模式的類圖定義如下
圖
類形式的類變壓器模式的類圖定義
在圖
可以看出
模式所涉及的成員有
目標(Target)
這就是我們所期待得到的接口
注意
由於這裡討論的是類變壓器模式
因此目標不可以是類
源(Adaptee)
現有需要適配的接口
變壓器(Adapter)
變壓器類是本模式的核心
變壓器把源接口轉換成目標接口
顯然
這一角色不可以是接口
而必須是實類
本模式的示范代碼如下
package com
javapatterns
adapter
classAdapter;
public interface Target
{
/**
* Class Adaptee contains operation sampleOperation
*/
void sampleOperation
();
/**
* Class Adaptee doesn
t contain operation sampleOperation
*/
void sampleOperation
();
}
代碼清單
Target的源代碼
package com
javapatterns
adapter
classAdapter;
public class Adaptee
{
public void
sampleOperation
(){}
}
代碼清單
Adaptee的源代碼
package com
javapatterns
adapter
classAdapter;
public class Adapter extends Adaptee implements Target
{
/**
* Class Adaptee doesn
t contain operation sampleOperation
*/
public void sampleOperation
()
{
// Write your code here
}
}
代碼清單
Adapter的源代碼
類形式的變壓器模式的效果
第一
使用一個實類把源(Adaptee)適配到目標(Target)
這樣一來
如果你想把源以及源的子類都使用此類適配
就行不通了
第二
由於變壓器類是源的子類
因此可以在變壓器類中置換(override)掉源的一些方法
第三
由於只引進了一個變壓器類
因此只有一個路線到達目標類
問題得到簡化
實例形式的變壓器模式的類圖定義如下
在圖
可以看出
模式所涉及的成員有
目標(Target)
這就是我們所期待得到的接口
目標可以是實的或抽象的類
源(Adaptee)
現有需要適配的接口
變壓器(Adapter)
變壓器類是本模式的核心
變壓器把源接口轉換成目標接口
顯然
這一角色必須是實類
本模式的示范代碼如下
package com
javapatterns
adapter;
public interface Target {
/**
* Class Adaptee contains operation sampleOperation
*/
void sampleOperation
();
/**
* Class Adaptee doesn
t contain operation sampleOperation
*/
void sampleOperation
();
}
代碼清單
Target的源代碼
package com
javapatterns
adapter;
public class Adapter implements Target {
public Adapter(Adaptee adaptee){
super();
this
adaptee = adaptee;
}
public void sampleOperation
(){ adaptee
sampleOperation
();
}
public void sampleOperation
(){
// Write your code here
}
private Adaptee adaptee;
}
代碼清單
Adapter的源代碼
package com
javapatterns
adapter;
public class Adaptee {
public void sampleOperation
(){}
}
代碼清單
Adaptee的源代碼
實例形式的變壓器模式的效果
第一
一個變壓器可以把多種不同的源適配到同一個目標
換言之
同一個變壓器可以把源類和它的子類都適配到目標接口
第二
與類形式的變壓器模式相比
要想置換源類的方法就不容易
如果一定要置換掉源類的一個或多個方法
就只好先做一個源類的子類
將源類的方法置換掉
然後再把源類的子類當作真正的源進行適配
第三
雖然要想置換源類的方法不容易
但是要想增加一些新的方法則方便得很
而且新增加的方法同時適用於所有的源
在什麼情況下使用變壓器模式
在以下各種情況下使用變壓器模式
第一
你需要使用現有的類
而此類的接口不符合你的需要
第二
你想要建立一個可以重復使用的類
用以與一些彼此之間沒有太大關聯的一些類
包括一些可能在將來引進的類一起工作
這些源類不一定有很復雜的接口
第三
(對實例形式的變壓器模式而言)你需要改變多個已有的子類的接口
如果使用類形式的變壓器模式
就要針對每一個子類做一個變壓器類
而這不太實際
J
SE中的變壓器模式的使用
在爪哇語言
的標准SDK中
有很多的變壓器類
如
庫程序包java\awt\event中有
ComponentAdapter
ContainerAdapter
FocusAdapter
HierarchyBoundsAdapter
KeyAdapter
MouseAdapter
MouseMotionAdapter
WindowAdapter
庫程序包Javax\swing\event中有
InternalFrameAdapter
MouseInputAdapter
這些都是變壓器模式使用的實際例子
值得指出的是
WindowAdapter的建立者們不可能預見到你所要使用的目標接口
因此WindowAdapter不可能實現你的目標接口
但是
在考察了這些變壓器類的使用范圍之後
我們會發現
WindowAdapter只需實現WindowListener的接口即可
也就是說
目標接口被省略了
請見下面的解釋
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27469.html