關於 Facade 本篇將討論以下幾個問題
1. 關於 Facade
2. UML
3. 將 UML 轉為程式碼
4. 情境
測試環境:
OS:Windows 10
IDE:Visual Studio 2019
1. 關於 Facade
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
by Gang of Four
- 為子系統提供統一的接口
- Facade 定義了一個更高級別的界面,使子系統更易於使用
Facade(門面)屬於結構型(Structural Patterns),用於整合時,對於系統中包含多個子系統,且子系統各自提供部分服務時,可藉由 Facade 將子系統整合,提供呼叫端完整服務。用於簡化時,對於系統中包含使用方式(e.g. 傳入參數)複雜的服務時,可藉由 Facade 將複雜服務中部分隱藏(簡化),只提供呼叫端部分(簡化過的)服務。
優點:
- 可簡化複雜系統的使用
缺點:
- 使用到 Facade 的部分耦合度提高
2. UML
Class 間關聯:
- Facade 關聯 SubSystem
Class:
- Facade:整合子系統服務並提供統一的外部接口
- SubSystem:系統中原有服務
3. 將 UML 轉為程式碼
系統中原有服務 SubSystemA / B / C / D
/// <summary>
/// 子系統 A
/// </summary>
public class SubSystemA
{
public void Method()
{
Console.WriteLine("SubSystemA Method");
}
}
/// <summary>
/// 子系統 B
/// </summary>
public class SubSystemB
{
public void Method()
{
Console.WriteLine("SubSystemB Method");
}
}
/// <summary>
/// 子系統 C
/// </summary>
public class SubSystemC
{
public void Method()
{
Console.WriteLine("SubSystemC Method");
}
}
/// <summary>
/// 子系統 D
/// </summary>
public class SubSystemD
{
public void Method()
{
Console.WriteLine("SubSystemD Method");
}
}
Facade 整合子系統並提供外部呼叫接口 MethodA / B
/// <summary>
/// Facade 整合子系統並提供外部呼叫接口
/// </summary>
public class Facade
{
private SubSystemA _subSystemA;
private SubSystemB _subSystemB;
private SubSystemC _subSystemC;
private SubSystemD _subSystemD;
public Facade()
{
_subSystemA = new SubSystemA();
_subSystemB = new SubSystemB();
_subSystemC = new SubSystemC();
_subSystemD = new SubSystemD();
}
public void MethodA()
{
Console.WriteLine("\nMethodA() ---- ");
_subSystemA.Method();
_subSystemB.Method();
_subSystemC.Method();
}
public void MethodB()
{
Console.WriteLine("\nMethodB() ---- ");
_subSystemB.Method();
_subSystemD.Method();
}
}
- 建立
facade
- 經由
facade
呼叫 MethodA / B
static void Main(string[] args)
{
Default.Facade facade = new Default.Facade();
facade.MethodA();
facade.MethodB();
Console.ReadLine();
}
執行結果
MethodA() ----
SubSystemA Method
SubSystemB Method
SubSystemC Method
MethodB() ----
SubSystemB Method
SubSystemD Method
4. 情境
我們接到了一個取得台北、台中、台南倉庫庫存的需求
- 取得庫存的 API 已寫好,但參數各不相同
- 提供一組呼叫介面,未來新增倉庫不用調整呼叫端
各地區取得庫存方法參數各自不同
/// <summary>
/// 台北庫存
/// </summary>
public class TaipeiInStock
{
public int GetInStock(int parameterA, string parameterB)
{
Console.WriteLine("台北庫存:100");
return 100;
}
}
/// <summary>
/// 桃園庫存
/// </summary>
public class TaoyuanInStock
{
public int GetInStock(int parameterA, string parameterB)
{
Console.WriteLine("桃園庫存:80");
return 80;
}
}
/// <summary>
/// 台中庫存
/// </summary>
public class TaichungInStock
{
public int GetInStock(bool parameterC)
{
Console.WriteLine("台中庫存:120");
return 120;
}
}
/// <summary>
/// 台南庫存
/// </summary>
public class TainanInStock
{
public int GetInStock()
{
Console.WriteLine("台南庫存:200");
return 200;
}
}
Facade 整合各地庫存加總後回傳
/// <summary>
/// Facade 整合各地庫存加總後回傳
/// </summary>
public class Facade
{
private TaipeiInStock _taipeiInStock;
private TaoyuanInStock _taoyuanInStock;
private TaichungInStock _taichungInStock;
private TainanInStock _tainanInStock;
public Facade()
{
_taipeiInStock = new TaipeiInStock();
_taoyuanInStock = new TaoyuanInStock();
_taichungInStock = new TaichungInStock();
_tainanInStock = new TainanInStock();
}
// 取得北台灣庫存
public int GetNorthernTaiwanInStock()
{
Console.WriteLine("\n ---- 取得北台灣庫存 ---- ");
var taipei = _taipeiInStock.GetInStock(default, default);
var taoyuan = _taoyuanInStock.GetInStock(default, default);
return taipei + taoyuan;
}
// 取得全台灣庫存
public int GetTaiwanInStock()
{
Console.WriteLine("\n ---- 取得全台灣庫存 ---- ");
var taipei = _taipeiInStock.GetInStock(default, default);
var taoyuan = _taoyuanInStock.GetInStock(default, default);
var taichung = _taichungInStock.GetInStock(default);
var tainan = _tainanInStock.GetInStock();
return taipei + taoyuan + taichung + tainan;
}
}
- 建立
facade
- 經由
facade
取得 北台灣庫存 & 全台灣庫存
static void Main(string[] args)
{
Situation.Facade facade = new Situation.Facade();
var northernTaiwanInStock = facade.GetNorthernTaiwanInStock();
Console.WriteLine($" ---- 北台灣庫存:{northernTaiwanInStock}");
var taiwanInStock = facade.GetTaiwanInStock();
Console.WriteLine($" ---- 全台灣庫存:{taiwanInStock}");
Console.ReadLine();
}
執行結果
---- 取得北台灣庫存 ----
台北庫存:100
桃園庫存:80
---- 北台灣庫存:180
---- 取得全台灣庫存 ----
台北庫存:100
桃園庫存:80
台中庫存:120
台南庫存:200
---- 全台灣庫存:500
完整程式碼
GitHub:Structural_05_Facade