設計模式:適配器模式

一:適配器模式的定義算法

  適配器模式:將一個類的接口轉換成客戶但願的另外一個接口。適配器模式讓那些接口不兼容的類能夠一塊兒工做編程

  Adapter Pattern:Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise because of incompatible interface.app

  適配器模式的別名爲包裝器(Wrapper)模式,它既能夠做爲類結構型模式,也能夠做爲對象結構型模式。在適配器模式定義中所說起的接口是指廣義的接口,它能夠表示一個方法或者方法的集合。測試

二:適配器模式的結構ui

  類適配器模式結構圖:this

  

  對象適配器結構圖:spa

    

 

  由圖可知適配器模式包含一下三個角色:設計

  1:Target(目標抽象類):目標抽象類定義客戶所需的接口,能夠是一個抽象類或接口,也能夠是具體類。在類適配器中,因爲C#語言不支持多重繼承,因此它只能是接口。code

  2:Adapter(適配器類):它能夠調用另外一個接口,做爲一個轉換器,對Adaptee和Target進行適配。它是適配器模式的核心。xml

  3:Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經存在的接口,這個接口須要適配,適配者類包好了客戶但願的業務方法。

 

三:適配器模式的實現

  1:類適配器

class Adapter : Adaptee, Target
{
    public void Request()
    {
        base.SpecificRequest();
    }
}

  2:對象適配器

class Adapter : Target
{
    private Adaptee adaptee; //維持一個對適配者對象的引用
    
    public Adapter(Adaptee adaptee)
    {
        this.adaptee = adaptee;
    }
    
    public void Request()
    {
        adaptee.SpecificRequest();//轉發調用
    }
}

  注意:在實際開發中對象適配器的使用頻率更高。

 

四:適配器模式的應用

  在爲某學校開發教務管理系統時,開發人員發現須要對學生成績進行排序和查找,該系統的設計人員已經開發了一個成績操做接口ScoreOperation,在該接口中聲明瞭排序方法Sort(int[]) 和查找方法Search(int[], int),爲了提升排序和查找的效率,開發人員決定重用現有算法庫中的快速排序算法類QuickSortClass和二分查找算法類BinarySearchClass,其中QuickSortClass的QuickSort(int[])方法實現了快速排序,BinarySearchClass的BinarySearch (int[], int)方法實現了二分查找。

 

因爲某些緣由,開發人員已經找不到該算法庫的源代碼,沒法直接經過複製和粘貼操做來重用其中的代碼;並且部分開發人員已經針對ScoreOperation接口編程,若是再要求對該接口進行修改或要求你們直接使用QuickSortClass類和BinarySearchClass類將致使大量代碼須要修改。

 

現使用適配器模式設計一個系統,在不修改已有代碼的前提下將類QuickSortClass和類BinarySearchClass的相關方法適配到ScoreOperation接口中。

  結構以下圖所示:

  

 

  ScoreOperation接口充當抽象目標,QuickScortClass和BinarySearchClass充當適配者,OperationAdapter充當適配器。

  (1)ScoreOperation:抽象成績操做類,充當目標接口

    public interface ScoreOperation
    {
        int[] Sort(int[] array);    //成績排序
        int Search(int[] array, int key);   //成績查找
    }

 

  (2)QuickSortClass:快速排序類,充當適配者

    public class QuickSortClass
    {
        public int[] QuickSort(int[] array)
        {
            Sort(array, 0, array.Length - 1);
            return array;
        }

        public void Sort(int[] array, int p, int r)
        {
            int q = 0;
            if(p < r)
            {
                q = Partition(array, p, r);
                Sort(array, p, q - 1);
                Sort(array, q + 1, r);
            }
        }

        public int Partition(int[] array, int p, int r)
        {
            int x = array[r];
            int j = p - 1;
            for (int i = p; i <= r - 1; i++)
            {
                if(array[i] <= x)
                {
                    j++;
                    Swap(array, j, i);
                }
            }
            Swap(array, j + 1, r);
            return j + 1;
        }

        public void Swap(int[] array, int i, int j)
        {
            int t = array[i];
            array[i] = array[j];
            array[j] = t;
        }
    }

  (3)BinarySearchClass:二分查找類,充當適配者

    public class BinarySearchClass
    {
        public int BinarySearch(int[] array, int key)
        {
            int low = 0;
            int high = array.Length - 1;
            while (low <= high)
            {
                int mid = (low + high) / 2;
                int midVal = array[mid];
                if (midVal < key)
                    low = mid + 1;
                else if (midVal > key)
                    high = mid - 1;
                else
                    return 1;   //找到元素返回1
            }
            return -1;  //未找到元素返回-1
        }
    }

  (4)OperationAdapter:操做適配器,充當適配器

    public class OperationAdapter : ScoreOperation
    {
        //定義適配者QuickSortClass對象
        private QuickSortClass sortObj; 
        //定義適配者BinarySearchClass對象
        private BinarySearchClass searchObj;    

        public OperationAdapter()
        {
            sortObj = new QuickSortClass();
            searchObj = new BinarySearchClass();
        }
        public int Search(int[] array, int key)
        {
            return searchObj.BinarySearch(array, key);
        }

        public int[] Sort(int[] array)
        {
            return sortObj.QuickSort(array);
        }
    }

  (5)配置文件App.config:在配置文件中存儲了適配器類的類名

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <appSettings>
    <add key="adapter" value="Model.AdapterSample.OperationAdapter"/>
  </appSettings>
</configuration>

  (6)Program:客戶端測試類

        static void Main(string[] args)
        {
            ScoreOperation operation;
            //讀取配置文件
            string adapterType = ConfigurationManager.AppSettings["adapter"];
            //經過反射生成對象
            operation = (ScoreOperation)Assembly.Load("Model.AdapterSample").CreateInstance(adapterType);

            int[] socres = { 84,76, 50, 69, 90, 92, 88, 86 };
            int[] result;
            int score;

            Console.WriteLine("程序的排序結果是:");
            result = operation.Sort(socres);

            //遍歷輸出成績
            foreach (var item in result)
                Console.Write(item+",");
            Console.WriteLine();

            Console.WriteLine("查找成績90:");
            score = operation.Search(result, 90);
            if(score!=-1)
                Console.WriteLine("找到成績90.");
            else
                Console.WriteLine("沒有找到成績90。");

            Console.WriteLine("查找成績92:");
            score = operation.Search(result, 920);
            if(score!=-1)
                Console.WriteLine("找到成績92.");
            else
                Console.WriteLine("沒有找到成績92。");

            Console.ReadKey();
        }

 

    

  

五:適配器模式的優缺點

   優勢:

    1:將目標類和適配者類解耦,經過引入一個適配器類來重用現有的適配者類,無需修改原有結構。

    2:增長了類的透明性和複用性,將具體的業務實現過程封裝在適配者類中,對於客戶端類而言是透明的,並且提升了適配者的複用性,同一適配者類能夠在多個不一樣的系統中複用。

    3:靈活性和擴展性都很是好,經過使用配置文件,能夠很方便的更換適配器,也能夠在不修改原有代碼的基礎上 增長新的適配器,徹底複合開閉原則。

  缺點:

    1:一次最多隻能適配一個適配者類,不能同時適配多個適配者。

    2:適配者類不能爲最終類,在C#中不能爲sealed類

    3:目標抽象類只能爲接口,不能爲類,其使用有必定的侷限性。

六:適配器模式的適用環境

   系統須要使用一些現有的類,而這些類的接口不符合系統的須要,甚至沒有這些類的源代碼

  建立一個能夠重複使用的類,用於和一些彼此之間沒有太大關聯的類,包括一些可能在未來引進的類一塊兒工做

七:缺醒適配器模式

   缺醒適配器模式(Default Adapter Pattern):當不須要實現一個接口所提供的全部方法時,可先設計一個抽象類實現該接口,併爲接口中的每一個方法提供一個默認實現(空方法),那麼該抽象類能夠有選擇性的覆蓋父類的某些方法來實現需求,它適用於不想使用一個接口中的全部方法的狀況,又稱爲單接口適配器模式。


由圖可知,在缺醒適配器模式中,包含如下三個角色:

  1:ServiceInsterface(適配者接口):它是一個接口,一般在該接口中聲明瞭大量的方法

  2:AbstractServiceClass(缺醒適配器類):它是缺醒適配器模式的核心類,使用空方法的形式實現了ServiceInterface接口中聲明的方法。一般將它定義爲抽象類,由於對它進行實例化也沒有任何意義。

  3:ConcreteServiceClass(具體業務類):它是缺醒適配器的子類,在沒有引入適配器以前,它須要實現適配者接口,所以須要實如今適配者接口中生命的全部方法,而對於一些無需使用的方法不得不提供空實現。有了缺醒適配器以後,能夠直接繼承該適配器類,根據須要有選擇性的覆蓋配置器類中定義的方法。

八:雙向適配器

   在對象適配器中若是同時包含目標類和適配者類的引用,適配者能夠經過它調用目標類中的方法,目標類也能夠經過它調用適配者類中的方法,那麼該適配器就是一個雙向適配器。

  雙向適配器結構示意圖:

  

示意代碼:

    public class Adapter:Target,Adaptee
    {
        //同時維持對抽象目標類和適配者類的引用
        private Target target;
        private Adaptee adaptee;

        public Adapter(Target target)
        {
            this.target = target;
        }
        public Adapter(Adaptee adatee)
        {
            this.adaptee = adatee;
        }

        public void Reqeust()
        {
            this.adaptee.SpecificRequest();
        }

        public void SpecificRequest()
        {
            this.target.Request();
        }
    }
相關文章
相關標籤/搜索