適配器主要用於接口的轉換或者將接口不兼容的類對象組合在一塊兒造成對外統一接口,是一種結構性模式,其本質是是一箇中間件,適用於類及其對象。
本文但願經過簡單的介紹和分析,能讓讀者對適配器模式有一個簡單直觀的認識和感知。html
對現有的類的接口進行轉換以符合新的需求。編程
經過轉換或者組合,間接複用已有功能模塊完成需求。數據結構
優勢:ide
缺點:spa
本文主要介紹前二者。設計
該模式並非在設計開發階段考慮的,主要用在想要修改一個已經存在的接口,或者組合若干關聯對象的時候。代理
下面是GoF介紹的典型的類適配器模式和對象適配器模式的UML類圖code
類適配器htm
原理:經過類繼承實現適配,繼承Target的接口,繼承Adaptee的實現中間件
對象適配器
原理:經過類對象組合實現適配
Target:
定義Client真正須要使用的接口。
Adaptee:
其中定義了一個已經存在的接口,也是咱們須要進行適配的接口。
Adapter:
對Adaptee和Target的接口進行適配,保證對target中接口的調用能夠間接轉換爲對Adaptee中接口進行調用。
接下來先將上面的UML類圖轉換爲兩個具體的例子,而後在對每一種類型在使用一個具體例子介紹.
下面咱們使用幾個例子來實際體驗一下代理模式的應用。
定義目標接口類:Target
public interface Target { void request(); }
被適配的類:Adaptee
public class Adaptee { public void adapteeRequest() { System.out.println("adapteeRequest method of Adaptee! "); } }
適配類Adapter,繼承Target的接口request,同時繼承Adaptee的實現adapteeRequest
public class Adapter extends Adaptee implements Target { @Override public void request() { // TODO Auto-generated method stub super.adapteeRequest(); } }
演示:
public class Demo { public static void main(String [] args) { Target target = new Adapter(); target.request(); // result: adapteeRequest method of Adaptee! } }
從上面兩張UML圖中能夠清楚的看出二者的區別,對象中Adapter不在繼承Adaptee,而是將Adaptee做爲一個數據成員組合到類定義中,從而實現對其接口的訪問。
public class Adapter implements Target { private Adaptee adaptee = new Adaptee(); @Override public void request() { // TODO Auto-generated method stub adaptee.adapteeRequest(); } }
考慮到某系統中有對數據排序的需求,下面使用適配器看一下如何複用現有的排序接口(下面的例子僅僅爲了演示,接口不具實際意義);
現有排序類:EffectiveVectorSort
public class EffectVectorSort { public void vectorSort() { System.out.println("vectorSort method of EffectVectorSort! "); } }
系統排序所需的接口類定義:DataSort
public interface DataSort { void sort(); }
定義適配器:SortAdapter
public class SortAdapter extends EffectVectorSort implements DataSort { @Override public void sort() { // TODO Auto-generated method stub super.vectorSort(); } }
演示:
public class Demo { public static void main(String [] args) { DataSort dataSort = new SortAdapter(); dataSort.sort(); // vectorSort method of EffectVectorSort! } }
若是系統中不只有對向量Vector的排序,也有對元組Tuple和鏈表LinkList等高級數據結構的排序,那麼顯然經過沒法經過類適配將每個排序類的子類都繼承。這裏即可以用到對象適配。
須要修改7.3中的SortAdapter,同時須要定義高級數據結構的排序類。
高級數據結構排序類接口:AdvanceDataSort
public interface AdvanceDataSort { void sort(); }
鏈表排序類:LinkListSort
public class LinkListSort implements AdvanceDataSort { @Override public void sort() { // TODO Auto-generated method stub System.out.println("sort method of LinkListSort!"); } }
元組排序類:TupleSort
public class TupleSort implements AdvanceDataSort { @Override public void sort() { // TODO Auto-generated method stub System.out.println("sort method of TupleSort"); } }
重定義適配器:SortAdapter
public class SortAdapter implements DataSort { private EffectVectorSort vectorSort = new EffectVectorSort(); private AdvanceDataSort listSort = new LinkListSort(); private AdvanceDataSort tupleSort = new TupleSort(); @Override public void sort(String dataType) { // TODO Auto-generated method stub if(dataType == "vector") { vectorSort.vectorSort(); } else if(dataType == "linklist") { listSort.sort(); } else if(dataType == "tuple") { tupleSort.sort(); } else { System.out.println("Invalid Data Type:" + dataType); } } }
演示:
public class Demo { public static void main(String [] args) { DataSort dataSort = new SortAdapter(); dataSort.sort("vector"); // vectorSort method of EffectVectorSort! dataSort.sort("linklist"); // sort method of LinkListSort! dataSort.sort("tuple"); // sort method of TupleSort dataSort.sort("dict"); // Invalid Data Type:dict } }
限於篇幅,先介紹到這裏。上面的例子都是比較直觀,簡單的。好好體會,將其應用到實際編程中才是咱們的目的。
參考:
GoF《Design Patterns: Elements of Reusable Object-Oriented Software》
https://www.runoob.com/design-pattern/adapter-pattern.html