天天看點

擴充卡模式(Adapter)一 概述二 類擴充卡模式三 對象擴充卡小結:

一 概述

定義:擴充卡模式将某個類的接口轉換成用戶端期望的另一個接口表示,主的目的是相容性,讓原本因接口不比對不能一起工作的兩個類可以協同工作。其别名為包裝器(Wrapper)。

屬于結構型模式

主要分為三類:類擴充卡模式、對象的擴充卡模式、接口的擴充卡模式。

本文定義:

需要被适配的類、接口、對象(我們有的),簡稱 src(source)

最終需要的輸出(我們想要的),簡稱 dst (destination,即Target)

擴充卡稱之為 Adapter 。

一句話描述擴充卡模式的感覺: src->Adapter->dst,即src以某種形式(三種形式分别對應三種擴充卡模式)給到Adapter裡,最終轉化成了dst。

使用場景:

1 系統需要使用現有的類,而這些類的接口不符合系統的需要。

2 想要建立一個可以重複使用的類,用于與一些彼此之間沒有太大關聯的一些類,包括一些可能在将來引進的類一起工作。

3 需要一個統一的輸出接口,而輸入端的類型不可預知。

二 類擴充卡模式

一句話描述:Adapter類,通過繼承 src類,實作 dst 類接口,完成src->dst的适配。

我們通過一個最常用的例子來說明

生活中最常見的就是充電器,220V的交流電被轉換成5V的直流電,充電器在其中就擔當了擴充卡的功能

既然我們是進行适配,那就說明是基于某一個功能點的實作,是以我們先定義一個輸出220v交流電的功能,這個功能如下

/// <summary>
    /// 220V電壓
    /// </summary>
    public class Voltage220
    {
        public int output220v()
        {
            int src = 220;
            Console.WriteLine("我是" + src + "伏電壓");
            return src;
        }
    }  
           

定義一個接口,接口的方法簽名是轉換(220V-5V)

/// <summary>
    /// 客戶需要的5V電壓接口
    /// </summary>
    public interface Voltage5
    {
        /// <summary>
        /// 輸出5V
        /// </summary>
        /// <returns></returns>
        int output5v();
    }
           

接下去我們開始定義擴充卡類

!!!注意點

1、繼承後來的類

2、實作擴充卡接口

/// <summary>
    /// 類擴充卡
    /// </summary>
    public class VoltageAdapter : Voltage220, Voltage5
    {
        public int output5v()
        {
            int src = new Voltage220().output220v();
            Console.WriteLine("擴充卡工作開始适配電壓");
            int dst = src / 44;
            Console.WriteLine("适配完成後輸出電壓:" + dst);
            return dst;
        }
    }
           

此時我們需要一個裝置,使用擴充卡檢視功能是否正确

定義一個手機類,實作轉換功能

Mobile.charging(擴充卡 box1)

執行個體化手機,調用充電方法,形參是擴充卡的執行個體

/// <summary>
    /// 手機類
    /// </summary>
    public class Mobile
    {
        /// <summary>
        /// 充電方法
        /// </summary>
        /// <param name="voltage5"></param>
        public void charging(Voltage5 voltage5)
        {
            if (voltage5.output5v() == 5)
            {
                Console.WriteLine("電壓剛剛好5V,開始充電");
            }
            else if (voltage5.output5v() > 5)
            {
                Console.WriteLine("電壓超過5V,都閃開 我要變成note7了");
            }
        }
    }
           

功能實作

/// <summary>
        /// 類擴充卡
        /// </summary>
        public static void ClassStart()
        {
            Console.WriteLine("===============類擴充卡==============");
            Mobile mobile = new Mobile();
            mobile.charging(new VoltageAdapter());
        }
           

三 對象擴充卡

基本思路和類的擴充卡模式相同,隻是将Adapter類作修改,這次不繼承src類,而是持有src類的執行個體,以解決相容性的問題。

即:持有 src類,實作 dst 類接口,完成src->dst的适配。

(根據“合成複用原則”,在系統中盡量使用關聯關系來替代繼承關系,是以大部分結構型模式都是對象結構型模式。)

/// <summary>
    /// 對象擴充卡
    /// </summary>
    public class VoltageAdapter2 : Voltage5
    {
        private Voltage220 voltage220;

        public VoltageAdapter2(Voltage220 voltage220)
        {
            this.voltage220 = voltage220;
        }

        public int output5v()
        {
            int dst = 0;
            if (null != voltage220)
            {
                int src = voltage220.output220v();
                Console.WriteLine("對象擴充卡工作,開始适配電壓");
                dst = src / 44;
                Console.WriteLine("适配完成後輸出電壓:" + dst);
            }
            return dst;
        }
    }
           
/// <summary>
        /// 對象擴充卡
        /// </summary>
        public static void ObjectStart()
        {
            Console.WriteLine("===============對象擴充卡==============");
            VoltageAdapter2 voltageAdapter2=new VoltageAdapter2(new Voltage220());
            Mobile mobile = new Mobile();
            mobile.charging(voltageAdapter2);
        }
           

小結:

對象擴充卡和類擴充卡其實算是同一種思想,隻不過實作方式不同。

根據合成複用原則,組合大于繼承,

是以它解決了類擴充卡必須繼承src的局限性問題,也不再強求dst必須是接口。

同樣的它使用成本更低,更靈活

繼續閱讀