關於 Adapter 本篇將討論以下幾個問題
1. 關於 Adapter
2. UML
3. 將 UML 轉為程式碼
4. 情境
測試環境:
OS:Windows 10
IDE:Visual Studio 2019
1. 關於 Adapter
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
by Gang of Four
- 將 Class 的接口再次封裝為呼叫端需要的樣子
- Adapter 使原本接口不相容的 Class 可以協同工作
Adapter(轉接器)屬於結構型(Structural Patterns),當遇到呼叫端與接收端無法對應時,經由 Adapter 的轉換,使得兩個接口不同的舊有 class 可以串接使用,而不需改變原本程式邏輯,以達到最小幅度修改的目的,一般而言 Adapter 常用於事後補救的情況。
優點:
- 符合 單一職責原則(Single Responsibility Principle)
- 符合 開閉原則(Open Closed Principle)
缺點:
- 過多的 Adapter 會造成整體程式複雜度提升
2. UML
Class 間關聯:
- Client 關聯 Target
- Adapter 繼承 Target
- Adapter 關聯 Adapter
Class:
- Client:呼叫端
- Target:依據呼叫端所定義的接口
- Adapter:轉接器實作,將
Adaptee
轉換為呼叫端所需的中間層 - Adaptee:欲呼叫但接口不合無法直接使用的被呼叫端
3. 將 UML 轉為程式碼
依據呼叫端所定義的接口
/// <summary>
/// 定義呼叫端使用的接口
/// </summary>
public interface ITarget
{
void Request();
}
被呼叫端所提供的接口
/// <summary>
/// 被呼叫端的接口
/// </summary>
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Called SpecificRequest()");
}
}
連接呼叫端與被呼叫端的Adapter
/// <summary>
/// 實作 Adapter
/// </summary>
public class Adapter : ITarget
{
private Adaptee _adaptee = new Adaptee();
public void Request()
{
_adaptee.SpecificRequest();
}
}
- 建立 Adapter
target
- 透過
target
呼叫 Adaptee
static void Main(string[] args)
{
Default.ITarget target = new Default.Adapter();
target.Request();
Console.ReadLine();
}
執行結果
Called SpecificRequest()
4. 情境
我們接到了一個取得倉庫庫存量資訊需要以 JSON 格式回傳的需求
- 原本服務回傳的格式為
List<InStockModel>
- 呼叫端需要的格式為 JSON
依據呼叫端所定義的接口,這邊預期會取回 sting 格式的 JSON 字串
/// <summary>
/// 定義呼叫端使用的接口
/// </summary>
public interface IInStock
{
string GetInStockData();
}
InStockService
回傳庫存資料格式為List<InStockModel>
/// <summary>
/// 被呼叫端的接口
/// </summary>
public class InStockService
{
public List<InStockModel> GetInStockData()
{
Console.WriteLine("Called InStockService GetInStockData()");
var inStockData = new List<InStockModel>
{
new InStockModel{Id = 1, Name = "AA", InStock = 100},
new InStockModel{Id = 2, Name = "BB", InStock = 200},
new InStockModel{Id = 3, Name = "CC", InStock = 300},
};
return inStockData;
}
}
/// <summary>
/// 庫存資料格式
/// </summary>
public class InStockModel
{
public int Id { get; set; }
public string Name { get; set; }
public int InStock { get; set; }
}
Adapter
將資料由List<InStockModel>
轉為 JSON 後回傳
/// <summary>
/// 實作 Adapter
/// </summary>
public class Adapter : IInStock
{
private InStockService _inStockService = new InStockService();
public string GetInStockData()
{
var inStockData = _inStockService.GetInStockData();
return JsonSerializer.Serialize(inStockData);
}
}
- 建立 Adapter
inStock
- 透過
inStock
取得 JSON 格式的 InStockData
static void Main(string[] args)
{
Situation.IInStock inStock = new Situation.Adapter();
var data = inStock.GetInStockData();
Console.WriteLine(data);
Console.ReadLine();
}
執行結果
Called InStockService GetInStockData()
[{"Id":1,"Name":"AA","InStock":100},{"Id":2,"Name":"BB","InStock":200},{"Id":3,"Name":"CC","InStock":300}]
完整程式碼
GitHub:Structural_01_Adapter