【設計模式-8】適配器模式

適配器結構圖:

Target(目標接口) 可以是接口或抽象類,由於c#不支持多類繼承,因此把Target定義爲接口
Adaptee(需要適配的類接口) 不滿足當前條件,需要轉化的類
Adapter(適配器) 負責Adaptee的接口與Target接口進行適配

優點:

  1. 通過適配器,客戶端可以調用同一接口,因而對客戶端來說是透明的。這樣做更簡單、更直接、更緊湊。
  2. 複用了現存的類,解決了現存類和複用環境要求不一致的問題
  3. 將目標類和適配者類解耦,通過引入一個適配器類重用現有的適配者類,而無需修改原有代碼。
  4. 一個對象適配器可以把多個不同的適配者類適配到同一個目標,也就是說,同一個適配器可以把適配者類和它的子類都適配到目標接口。

缺點:

  對於對象適配器來說,更換適配器的實現過程比較複雜

適配器模式適用情形:

  1. 當適用一個已存在的類,而它的接口不符合所要求的情況;
  2. 想要創建一個可以複用的類,該類可以與原接口的類協調工作;
  3. 在對象適配中,當要匹配數個子類的時候,對象適配器可以適配它們的父類接口。

類的適配器模式:

   //Target(目標接口) 需要的電壓
    public interface America_Dian
    {
        int Dian_110();
    }

    //Adaptee(需要適配的類接口) 現有的電壓
    public class China_Dian
    {
        public int Dian_220()
        {
            return 220;
        }
    }


    //Adapter(適配器) 110v電壓變爲220v電壓
    public class Transform_Dian:China_Dian,America_Dian
    {
        public int Dian_110()
        {
            int tempDianV = this.Dian_220();
            if(tempDianV == 220)
            {
                return 110;
            }
            Debug.Log("沒有電壓成功,這回好了,機器燒了");
            return tempDianV;
        }
    }

    public class ImportedMachine
    {
        public void Work(int _dianV)
        {
            if(_dianV == 110)
            {
                Debug.Log("變壓成功,美國進口機器在中國運行正常");
            }
        }
    }

    public void Start()
    {
        Transform_Dian tempTransform_Dian = new Transform_Dian();
        //進口美國電器還是用美國的充電線 但是經過變壓器把電壓從220v升到了110v
        int tempDianV = tempTransform_Dian.Dian_110();
        ImportedMachine tempMachine = new ImportedMachine();
        //升壓後,
        tempMachine.Work(tempDianV);
    }

對象適配器:

//Target(目標接口) 需要的電壓
    public interface America_Dian
    {
        int Dian_110();
    }

    //Adaptee(需要適配的類接口) 現有的電壓
    public class China_Dian
    {
        public int Dian_220()
        {
            return 220;
        }
    }


    //Adapter(適配器) 110v電壓變爲220v電壓
    //不用繼承而是委派
    public class Transform_Dian:America_Dian
    {
        //直接關聯被適配類
        private China_Dian m_chinaDian;

        public Transform_Dian(China_Dian _chinaDian)
        {
            this.m_chinaDian = _chinaDian;
        }
        public int Dian_110()
        {
            int tempDianV = m_chinaDian.Dian_220();
            if(tempDianV == 220)
            {
                return 110;
            }
            Debug.Log("沒有電壓成功,這回好了,機器燒了");
            return tempDianV;
        }
    }

    public class ImportedMachine
    {
        public void Work(int _dianV)
        {
            if(_dianV == 110)
            {
                Debug.Log("變壓成功,美國進口機器在中國運行正常");
            }
        }
    }

    public void Start()
    {
        Transform_Dian tempTransform_Dian = new Transform_Dian(new China_Dian());
        //進口美國電器還是用美國的充電線 但是經過變壓器把電壓從110v升到了220v
        int tempDianV = tempTransform_Dian.Dian_110();
        ImportedMachine tempMachine = new ImportedMachine();
        //升壓後,
        tempMachine.Work(tempDianV);
    }

對象適配器和類適配器其實算是同一種思想,只不過實現方式不同。 
根據合成複用原則,組合大於繼承, 
所以它解決了類適配器必須繼承Adaptee的侷限性問題,也不再強求Target必須是接口。 
同樣的它使用成本更低,更靈活

接口適配器:

   //不同電器,電機所需電壓不同
    public interface DianYa
    {
        int Output5v();
        int Output10v();
        int Output15v();
        int Output20v();
    }

    //適配器 抽象類實現接口,而在抽象類中所有的方法都進行置空
    public abstract class Adapter:DianYa
    {
        public int Output5v()
        {
            return 220;
        }
        public int Output10v()
        {
            return 220;
        }
        public int Output15v()
        {
            return 220;
        }
        public int Output20v()
        {
            return 220;
        }
    }

    //本類根據需要,從繼承的抽象類中,選擇性的實現自己需要的方法
    public class Phone:Adapter
    {
        public int Output5v()
        {
            int tempOutputV = base.Output5v();
            if(tempOutputV == 220)
            {
                Debug.Log("220->5 變壓成功,手機可以充電了");
                return 5;
            }
            Debug.Log("變壓失敗,這回好了,手機燒了");
            return tempOutputV;
        }
    }

    public class Computer:Adapter
    {
        public int Output15v()
        {
            int tempOutputV = base.Output15v();
            if(tempOutputV == 220)
            {
                Debug.Log("220->15 變壓成功,電腦可以充電了");
                return 15;
            }
            Debug.Log("變壓失敗,這回好了,電腦燒了");
            return tempOutputV;
        }
    }

    public void Start()
    {
        Phone tempPhone = new Phone();
        tempPhone.Output5v();

        Computer tempComputer = new Computer();
        tempComputer.Output15v();
    }
  • 類適配器,以類給到,在Adapter裏,就是將Adaptee當做類,繼承, 
  • 對象適配器,以對象給到,在Adapter裏,將Adaptee作爲一個對象,持有。 
  • 接口適配器,以接口給到,在Adapter裏,將Adaptee作爲一個接口,實現

參考:

https://www.cnblogs.com/libingql/p/3495699.html

https://www.jianshu.com/p/9d0575311214

http://www.manew.com/thread-100219-1-1.html

https://www.cnblogs.com/V1haoge/p/6479118.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章