讓多個對象都有機會處理請求,避免發送者與接收者耦合。將對象連成鏈,沿鏈傳遞請求,直到有對象處理為止。
遊戲客服系統:普通客服、客服經理、客服總監三角色。處理規則:
若客戶端直接依賴三角色並協調流程,會知曉過多細節。引入責任鏈,客戶端僅需拋給入口點。
using System;
using System.Collections.Generic;
using System.Text;
namespace ChainOfRespExample
{
class Program
{
static List<CustomerService> gmTeam = new List<CustomerService>();
static List<CustomerService> managerTeam = new List<CustomerService>();
static List<CustomerService> directorTeam = new List<CustomerService>();
static Random random = new Random();
static void InitCOR()
{
if (managerTeam.Count > 0)
foreach (var cs in gmTeam) cs.SetLeader(managerTeam[random.Next(managerTeam.Count)]);
else
foreach (var cs in gmTeam) cs.SetLeader(directorTeam[random.Next(directorTeam.Count)]);
foreach (var cs in managerTeam) cs.SetLeader(directorTeam[random.Next(directorTeam.Count)]);
}
static void InitGM()
{
for (int i = 1; i <= 9; i++)
{
var gm = new NormalGM("gm" + i);
gm.SetResponsibleCaseCategory(new int[] { 1, 2 });
gmTeam.Add(gm);
}
for (int i = 1; i <= 2; i++)
{
var m = new GMManager("manager" + i);
m.SetResponsibleCaseCategory(new int[] { 3, 4 });
managerTeam.Add(m);
}
for (int i = 1; i <= 1; i++) directorTeam.Add(new GMDirector("director" + i));
}
static void Main(string[] args)
{
InitGM();
InitCOR();
var gm = gmTeam[random.Next(gmTeam.Count)];
gm.HandleCase(new Case(1, false));
Console.WriteLine(Environment.NewLine);
gm = gmTeam[random.Next(gmTeam.Count)];
gm.HandleCase(new Case(2, true));
Console.WriteLine(Environment.NewLine);
gm = gmTeam[random.Next(gmTeam.Count)];
gm.HandleCase(new Case(3, false));
Console.WriteLine(Environment.NewLine);
gm = gmTeam[random.Next(gmTeam.Count)];
gm.HandleCase(new Case(4, true));
Console.WriteLine(Environment.NewLine);
gm = gmTeam[random.Next(gmTeam.Count)];
gm.HandleCase(new Case(5, true));
}
}
class Case
{
public int CaseCategory { get; }
public bool ImportantCase { get; }
public string Reply { get; set; }
public Case(int cat, bool imp) { CaseCategory = cat; ImportantCase = imp; }
}
abstract class CustomerService
{
protected CustomerService leader;
protected List<int> responsibleCaseCategory = new List<int>();
protected string name;
public string Name => name;
public CustomerService(string name) { this.name = name; }
public void SetLeader(CustomerService leader) => this.leader = leader;
public abstract void HandleCase(Case gameCase);
public void SetResponsibleCaseCategory(int[] cats) => cats.ToList().ForEach(c => responsibleCaseCategory.Add(c));
}
class NormalGM : CustomerService
{
public NormalGM(string name) : base(name) { }
public override void HandleCase(Case gameCase)
{
if (responsibleCaseCategory.Contains(gameCase.CaseCategory))
{
gameCase.Reply = "OK";
Console.WriteLine($"The case has been replied by {name}");
if (gameCase.ImportantCase)
{
Console.WriteLine("The reply should be checked.");
leader.HandleCase(gameCase);
}
else Console.WriteLine("The reply has been sent to player.");
}
else if (leader != null)
{
Console.WriteLine($"{name} reports this case to {leader.Name}.");
leader.HandleCase(gameCase);
}
}
}
class GMManager : CustomerService
{
public GMManager(string name) : base(name) { }
public override void HandleCase(Case gameCase)
{
if (responsibleCaseCategory.Contains(gameCase.CaseCategory))
{
gameCase.Reply = "OK";
Console.WriteLine($"The case has been replied by {name}");
if (gameCase.ImportantCase)
{
Console.WriteLine("The reply should be checked.");
leader.HandleCase(gameCase);
}
else Console.WriteLine("The reply has been sent to player.");
}
else if (gameCase.Reply != null)
{
Console.WriteLine($"The case has been checked by {name}");
Console.WriteLine("The reply has been sent to player.");
}
else if (leader != null)
{
Console.WriteLine($"{name} reports this case to {leader.Name}.");
leader.HandleCase(gameCase);
}
}
}
class GMDirector : CustomerService
{
public GMDirector(string name) : base(name) { }
public override void HandleCase(Case gameCase)
{
if (gameCase.Reply != null)
{
Console.WriteLine($"The case has been checked by {name}");
Console.WriteLine("The reply has been sent to player.");
}
else
{
gameCase.Reply = "OK";
Console.WriteLine($"The case has been replied by {name}");
Console.WriteLine("The reply has been sent to player.");
}
}
}
}
leader 參考與責任分類清單,定義統一 HandleCase。InitGM 建立團隊(9 GM、2 經理、1 總監);InitCOR 動態建鏈(無經理時 GM 直連總監);隨機指派 GM 為入口處理 5 種案例。