設計模式之適配器模式(adapter pattern)

適配器主要用於接口的轉換或者將接口不兼容的類對象組合在一塊兒造成對外統一接口,是一種結構性模式,其本質是是一箇中間件,適用於類及其對象。
本文但願經過簡單的介紹和分析,能讓讀者對適配器模式有一個簡單直觀的認識和感知。html

1.目的

對現有的類的接口進行轉換以符合新的需求。編程

2.動機

經過轉換或者組合,間接複用已有功能模塊完成需求。數據結構

3.優缺點

優勢:ide

  1. 提升了類的複用;
  2. 組合若干關聯對象造成對外提供統一服務的接口;
  3. 擴展性、靈活性好。

缺點:spa

  1. 過多使用適配模式容易形成代碼功能和邏輯意義的混淆。
  2. 部分語言對繼承的限制,可能至多隻能適配一個適配者類,並且目標類必須是抽象類。

4.分類

  • 類適配器
  • 對象適配器
  • 接口適配器

  本文主要介紹前二者。設計

5.主要用途及場景

該模式並非在設計開發階段考慮的,主要用在想要修改一個已經存在的接口,或者組合若干關聯對象的時候。代理

  1. 想用一個已經存在的類,但其接口不符合需求;
  2. 想建立一個能夠複用的類,該類能夠與其餘不相關的類協同工做;
  3. 想使用一些已經存在的子類,可是不能對每個都進行子類化以匹配它們的接口(僅適用於對象Adapter)。對象適配器能夠適配他的父類接口。

6.原理

下面是GoF介紹的典型的類適配器模式和對象適配器模式的UML類圖code

類適配器htm

原理:經過類繼承實現適配,繼承Target的接口,繼承Adaptee的實現中間件

對象適配器

原理:經過類對象組合實現適配

Target:

 定義Client真正須要使用的接口。

Adaptee:

 其中定義了一個已經存在的接口,也是咱們須要進行適配的接口。

Adapter:

 對Adaptee和Target的接口進行適配,保證對target中接口的調用能夠間接轉換爲對Adaptee中接口進行調用。

7.實現

接下來先將上面的UML類圖轉換爲兩個具體的例子,而後在對每一種類型在使用一個具體例子介紹.
下面咱們使用幾個例子來實際體驗一下代理模式的應用。

7.1 類適配器

 定義目標接口類: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! 
    }
}

  7.2 對象適配器

從上面兩張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();
    }
}

7.3 類適配器實例——排序

考慮到某系統中有對數據排序的需求,下面使用適配器看一下如何複用現有的排序接口(下面的例子僅僅爲了演示,接口不具實際意義);

現有排序類: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! 
    }
}

7.4對象適配器實例——排序

若是系統中不只有對向量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

相關文章
相關標籤/搜索