本章介紹 PROXY 模式與 GATEWAY 模式(特別是 Table Data Gateway),說明它們如何管理物件與外部系統(資料庫、第三方 API)之間的關係。
PROXY 模式#
動機:購物車問題#

Figure 34.1: Simple shopping cart object model

Figure 34.2: Shopping cart relational data model
- 有一個簡單的購物車物件模型(
Product、Order、Item),但需要將資料持久化到關聯式資料庫 - 問題:商業邏輯不應該知道資料庫的存在——如果
Product類別直接包含 SQL 程式碼,就違反了 SRP
PROXY 的三方拆分#

Figure 34.3: PROXY static model

Figure 34.4: PROXY dynamic model
- PROXY 將一個物件拆成三個部分:
- 介面(如
Product):宣告業務方法 - 實作(如
ProductImplementation):包含純粹的業務邏輯 - Proxy(如
ProductDBProxy):也實作介面,但在業務方法之外加入資料庫存取邏輯
- 介面(如
public interface Product
{
string Name { get; set; }
double Price { get; set; }
}
public class ProductDBProxy : Product
{
private string name;
private double price;
public string Name
{
get
{
// 延遲載入:如果尚未從資料庫讀取,先讀取
if (name == null)
LoadFromDatabase();
return name;
}
set
{
name = value;
SaveToDatabase();
}
}
// ...
}- 客戶端只知道
Product介面,不知道背後是記憶體版本還是資料庫 Proxy - 測試時使用
ProductImplementation,正式環境使用ProductDBProxy
依賴反轉#

Figure 34.5: Initial relationship between an application and a third-party

Figure 34.7: Inverting the dependency between the application and the

Figure 34.8: How the Proxy inverts the dependency between the
- PROXY 模式自然地實現了 DIP:應用程式依賴抽象介面,Proxy 是橋接抽象與具體實作的機制
- 第三方程式庫的依賴被隔離在 Proxy 中,應用程式核心完全不受影響
重點: PROXY 模式的核心價值是透明性——客戶端完全不知道它操作的是 Proxy 而非真實物件。這讓持久化、遠端呼叫、快取等橫切關注點可以在不修改業務邏輯的情況下加入。
GATEWAY 模式#
Table Data Gateway#

Figure 34.9: TABLE DATA GATEWAY pattern
- Table Data Gateway(TDG) 是一種特殊的 FACADE,為資料庫表格提供 CRUD 操作的統一介面
- 每個資料表對應一個 Gateway 類別,封裝所有相關的 SQL 操作
public interface EmployeeGateway
{
void AddEmployee(int empId, string name, string address);
DataRow GetEmployee(int empId);
void DeleteEmployee(int empId);
}
public class SqlEmployeeGateway : EmployeeGateway
{
public void AddEmployee(int empId, string name, string address)
{
string sql = "INSERT INTO Employee VALUES (@id, @name, @address)";
// 執行 SQL...
}
// ...
}測試用的記憶體 Gateway#
- 為了測試,可以建立
InMemoryEmployeeGateway,用Dictionary或DataTable取代真實資料庫 - 這與 FACTORY 模式搭配使用:測試時注入記憶體 Gateway,正式環境注入 SQL Gateway
技巧: Table Data Gateway 的命名慣例是「表名 + Gateway」,如
EmployeeGateway、OrderGateway。介面定義在高層模組中,具體實作(SqlEmployeeGateway)放在低層模組中,確保 DIP。
PROXY vs. GATEWAY#
| 特性 | PROXY | GATEWAY |
|---|---|---|
| 粒度 | 物件層級 | 表格/服務層級 |
| 透明性 | 客戶端不知道 Proxy 的存在 | 客戶端明確使用 Gateway |
| 典型用途 | 延遲載入、遠端呼叫、存取控制 | 資料庫存取、第三方 API 封裝 |
| 複雜度 | 較高(三方拆分) | 較低(簡單封裝) |
補充: 在實務中,PROXY 和 GATEWAY 可以搭配使用——例如 GATEWAY 負責與資料庫通訊,而 PROXY 利用 GATEWAY 來實現物件的透明持久化。
本章小結#
PROXY 模式透過三方拆分(介面、實作、代理)實現了物件的透明代理,讓橫切關注點(如持久化)不會污染業務邏輯。GATEWAY 模式(特別是 Table Data Gateway)則提供了更簡單直接的方式來封裝外部系統的存取,兩者都是建構可測試、可維護系統的重要工具。