以一個中介對象封裝一組對象的交互,使各對象無需顯式相互引用,達到鬆散耦合,且能獨立變更交互行為。
網路遊戲多大區架構:每大區為一組伺服器,擁有獨立資料庫。新需求:玩家資訊跨大區共享(註冊同步、充值通知、消費同步)。
若無中介者,A、B、C 三大區需兩兩互呼叫,耦合極高。引入 AccountSystem 作為中介者:
引入前:網站呼叫 A/B/C 註冊 → A 充值呼叫 B/C → B 充值呼叫 A/C → …(N² 複雜度)
引入後:
步驟 1-2 即為 Facade 模式;加上 3-6 雙向協調,AccountSystem 成為 Mediator。
using System;
using System.Collections.Generic;
using System.Text;
namespace MediatorExample
{
class Program
{
static void Main(string[] args)
{
AccountSystem accountSystem = new AccountSystem();
GameSystem gameArea1 = new GameArea1(accountSystem);
GameSystem gameArea2 = new GameArea2(accountSystem);
accountSystem.RegisterGameArea(gameArea1);
accountSystem.RegisterGameArea(gameArea2);
string userName = "aaa";
accountSystem.CreateAccount(userName);
gameArea1.Recharge(userName, 200);
gameArea2.Consume(userName, 50);
accountSystem.QueryBalance(userName);
}
}
class AccountSystem
{
Dictionary<string, int> userBalance = new Dictionary<string, int>();
List<GameSystem> gameAreaList = new List<GameSystem>();
public void RegisterGameArea(GameSystem gs) => gameAreaList.Add(gs);
public void CreateAccount(string userName)
{
userBalance[userName] = 0;
foreach (var gs in gameAreaList) gs.CreateAccountSelf(userName);
}
public void Recharge(string userName, int amount)
{
if (!userBalance.ContainsKey(userName)) return;
bool ok = true;
foreach (var gs in gameAreaList) ok &= gs.RechargeSelf(userName, amount);
if (ok) userBalance[userName] += amount;
}
public void Consume(string userName, int amount)
{
if (!userBalance.ContainsKey(userName)) return;
bool ok = true;
foreach (var gs in gameAreaList) ok &= gs.ConsumeSelf(userName, amount);
if (ok) userBalance[userName] -= amount;
}
public void QueryBalance(string userName) => Console.WriteLine($"Your balance is {userBalance[userName]}");
}
abstract class GameSystem
{
protected AccountSystem accountSystem;
protected Dictionary<string, int> userBalance = new Dictionary<string, int>();
protected GameSystem(AccountSystem accountSystem) => this.accountSystem = accountSystem;
internal virtual bool CreateAccountSelf(string userName)
{
userBalance[userName] = 0; return true;
}
internal virtual bool RechargeSelf(string userName, int amount)
{
if (userBalance.ContainsKey(userName)) userBalance[userName] += amount;
return true;
}
internal virtual bool ConsumeSelf(string userName, int amount)
{
if (userBalance.ContainsKey(userName)) userBalance[userName] -= amount;
return true;
}
public void Recharge(string userName, int amount) => accountSystem.Recharge(userName, amount);
public void Consume(string userName, int amount) => accountSystem.Consume(userName, amount);
}
class GameArea1 : GameSystem
{
public GameArea1(AccountSystem a) : base(a) { }
internal override bool CreateAccountSelf(string userName)
{
Console.WriteLine($"{userName} Registered in GameArea1");
return base.CreateAccountSelf(userName);
}
internal override bool RechargeSelf(string userName, int amount)
{
base.RechargeSelf(userName, amount);
Console.WriteLine($"{userName}'s amount in GameArea1 is {userBalance[userName]}");
return true;
}
internal override bool ConsumeSelf(string userName, int amount)
{
base.ConsumeSelf(userName, amount);
Console.WriteLine($"{userName}'s amount in GameArea1 is {userBalance[userName]}");
return true;
}
}
class GameArea2 : GameSystem
{
public GameArea2(AccountSystem a) : base(a) { }
internal override bool CreateAccountSelf(string userName)
{
Console.WriteLine($"{userName} Registered in GameArea2");
return base.CreateAccountSelf(userName);
}
internal override bool RechargeSelf(string userName, int amount)
{
base.RechargeSelf(userName, amount);
Console.WriteLine($"{userName}'s amount in GameArea2 is {userBalance[userName]}");
return true;
}
internal override bool ConsumeSelf(string userName, int amount)
{
base.ConsumeSelf(userName, amount);
Console.WriteLine($"{userName}'s amount in GameArea2 is {userBalance[userName]}");
return true;
}
}
}
gameAreaList。xxxSelf),全部成功後才更新自身帳戶餘額。Recharge/Consume 僅轉發給 Mediator;供 Mediator 呼叫的 xxxSelf 執行實際邏輯。當一組介面相對穩定的對象之間依賴關係錯綜複雜、難以維護或可能變動時,考慮 Mediator。
delegate 解耦 Mediator 與同事的交互行為。