設計模式筆記:介面卡模式(Adapter)

libingql發表於2013-12-28

1. 介面卡模式簡介

1.1 模式定義

  介面卡模式:通過一個類的介面轉換成客戶希望的另外一個介面,使原本由於介面不相容而不能一起工作的那些類可以一起工作

  介面卡從結構上分為:類介面卡和物件介面卡。其中類介面卡使用繼承關係來對類進行適配,物件介面卡使用物件引用來進行適配。

  C#實現類介面卡時,Target只能是介面。實現物件介面卡時,Target可以是抽象類也可以是介面。

1.2 使用頻率

   中高

2. 類介面卡模式結構

2.1 結構圖

2.1.1 類介面卡結構圖

2.1.2 物件介面卡結構圖

2.2 參與者

  介面卡模式參與者:

  ◊ Target:Client所使用的目標介面,可以是介面或抽象類。由於C#/Java不支援多類繼承,故把Target定義為介面。

  ◊ Adaptee:需要適配的類介面。

  ◊ Adapter:介面卡,負責Adaptee的介面與Target介面進行適配。

  ◊ Client:與符合Target介面的物件協調的類。

  在介面卡模式中,類Adapter實現介面卡的功能,它在Client於Adaptee之間加入Adapter,這樣Client把請求發給介面為Target的類Adapter,再由Adapter呼叫Adaptee,從而實現Client呼叫Adaptee。

3. 介面卡模式結構實現

3.1 類介面卡結構實現

  ITarget.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
    public interface ITarget
    {
        void Request();
    }
}

  Adaptee.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
    public class Adaptee
    {
        public void SpecificRequest()
        {
            Console.WriteLine("Called SpecificRequest()");
        }
    }
}

  Adapter.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
    public class Adapter : Adaptee, ITarget
    {
        public void Request()
        {
            this.SpecificRequest();
        }
    }
}

  Client.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ClassAdapter
{
    public class Client
    {
        static void Main(string[] args)
        {
            ITarget t = new Adapter();
            t.Request();
        }
    }
}

  執行輸出:

Called SpecificRequest()
請按任意鍵繼續. . .

3.2 物件介面卡結構實現

  Client需要呼叫Request方法,而Adaptee並沒有該方法,為了使Client能夠使用Adaptee類,需要提供一個類Adapter。這個類包含了一個Adaptee的例項,將Client與Adaptee銜接起來。

  ITarget.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
    public interface ITarget
    {
        void Request();
    }
}

  Target.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
    public class Target : ITarget
    {
        public virtual void Request()
        {
            Console.WriteLine("Called Target Request()");
        }
    }
}

  Adaptee.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
    public class Adaptee
    {
        public void SpecificRequest()
        {
            Console.WriteLine("Called SpecificRequest()");
        }
    }
}

  Adapter.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
    public class Adapter : Target
    {
        private Adaptee _adaptee = new Adaptee();

        public override void Request()
        {
            _adaptee.SpecificRequest();
        }
    }
}

  Client.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Structural.ObjectAdapter
{
    public class Client
    {
        static void Main(string[] args)
        {
            ITarget t = new Adapter();
            t.Request();
        }
    }
}

4. 介面卡模式實踐應用

  以手機充電的電源介面卡為例,用介面卡模式的解決方案。

4.1 類介面卡結構實現

  ITarget.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
    public interface ITarget
    {
        void GetPower();
    }
}

  Power.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
    public class Power
    {
        public void GetPower220V()
        {
            Console.WriteLine("從電源中得到220V的電壓");
        }
    }
}

  Adapter.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
    public class Adapter : Power, ITarget
    {
        public void GetPower()
        {
            this.GetPower220V();
            Console.WriteLine("得到手機的充電電壓!");
        }
    }
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ClassAdapter
{
    public class Client
    {
        static void Main(string[] args)
        {
            Console.WriteLine("手機:");
            ITarget t = new Adapter();
            t.GetPower();
        }
    }
}

  執行輸出:

手機:
從電源中得到220V的電壓
得到手機的充電電壓!
請按任意鍵繼續. . .

4.2>、物件介面卡結構實現

  ITarget.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
    public interface ITarget
    {
        void GetPower();
    }
}

  Power.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
    public class Power
    {
        public void GetPower220V()
        {
            Console.WriteLine("從電源中得到220V的電壓");
        }
    }
}

  Adapter.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
    public class Adapter : ITarget
    {
        public Power _power;
        public Adapter(Power power)
        {
            this._power = power;
        }

        /// <summary>
        /// 得到想要的電壓
        /// </summary>
        public void GetPower()
        {
            _power.GetPower220V();
            Console.WriteLine("得到手機的充電電壓!");
        }
    }
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AdapterPattern.Practical.ObjectAdapter
{
    public class Client
    {
        static void Main(string[] args)
        {
            Console.WriteLine("手機:");
            ITarget t = new Adapter(new Power());
            t.GetPower();
        }
    }
}

5、介面卡模式應用分析

  介面卡模式適用情形:

  ◊ 當適用一個已存在的類,而它的介面不符合所要求的情況;

  ◊ 想要建立一個可以複用的類,該類可以與原介面的類協調工作;

  ◊ 在物件適配中,當要匹配數個子類的時候,物件介面卡可以適配它們的父類介面。

    介面卡模式特點:

  類介面卡

  ◊ 使得Adapter可以重定義Adaptee的部分行為。因為Adapter是Adaptee的一個子類;

  ◊ 僅僅引入了一個物件,並不需要額外的指標間接得到Adaptee。

  物件介面卡

  ◊ 允許一個Adapter與多個Adaptee同時工作。Adapter也可以一次給所有的Adaptee新增功能;

  ◊ 使得重定義Adaptee的行為比較困難。需要生成一個Adaptee的子類,然後使Adapter引入這個子類而不是引用Adaptee本身。

相關文章