Unity 责任链模式
初学者,自用笔记
用于把“一个请求的处理逻辑”拆成多个独立的处理器(Handler),并按顺序串成一条链;请求沿链传递,每个处理器决定:处理它、补充处理、拦截终止、或交给下一个。这样可以把复杂的 if/else、switch、规则判断解耦成可插拔的步骤,方便扩展与重排
常用于任务系统、成就系统、技能判定等......
- Request(请求对象)主要携带输入参数(例如:玩家、任务ID、事件类型)
- Handler(抽象处理器):定义统一处理入口(如 Handle(request))并持有 next。
- ConcreteHandler(具体处理器):实现具体规则/步骤(校验、过滤、转换、执行、日志、冷却判定等)。
- Client(组链者/调用方):负责把各处理器按顺序组装成链,并发起请求。
简单例子
Request
public sealed class QuestRequest
{
// 输入(由调用方填)
public int PlayerId;
public int QuestId;
// 链上产物/状态(由处理器写)
public bool Allowed = true;
public string FailReason = "";
// 控制责任链:是否继续往下传
public bool StopPropagation = false;
}
Handler
public abstract class QuestHandler
{
protected QuestHandler _next;
public QuestHandler SetNext(QuestHandler next)
{
_next = next;
return next; // 方便链式组装
}
// 统一入口:把 request 放进来
public void Handle(QuestRequest request)
{
// 1.先由当前处理器处理
OnHandle(request);
// 2.决定是否继续传递
if (request.StopPropagation) return;
if (_next == null) return;
// 3.交给下一个
_next.Handle(request);
}
// 具体处理逻辑由子类实现
protected abstract void OnHandle(QuestRequest request);
}
ConcreteHandler
public sealed class PrerequisiteQuestCheckHandler : QuestHandler
{
// 检查前置任务是否满足(不满足则拒绝并中断链)
protected override void OnHandle(QuestRequest request)
{
// 假设一个任务可能有多个前置任务ID
var prereqQuestIds = FakeQuestDB.GetPrerequisites(request.QuestId);
for (int i = 0; i < prereqQuestIds.Length; i++)
{
int prereqId = prereqQuestIds[i];
if (!FakeQuestDB.IsCompleted(request.PlayerId, prereqId))
{
request.Allowed = false; // 不允许接取
request.FailReason = $"";
request.StopPropagation = true; // 拦截:后续不用检查了
return;
}
}
}
}
public sealed class LevelCheckHandler : QuestHandler
{
// 检查玩家等级是否满足接取条件
protected override void OnHandle(QuestRequest request)
{
int playerLevel = FakePlayerDB.GetLevel(request.PlayerId); // 查询玩家等级
if (playerLevel < 10) // 未达标:拒绝并中断后续处理
{
request.Allowed = false; // 标记不允许
request.FailReason = ""; // 写入失败原因
request.StopPropagation = true; // 拦截:不再传给 next
}
}
}
public sealed class QuestStateCheckHandler : QuestHandler
{
// 检查任务是否已完成(已完成则不能再接取)
protected override void OnHandle(QuestRequest request)
{
bool isQuestAlreadyCompleted =
FakeQuestDB.IsCompleted(request.PlayerId, request.QuestId); // 查询任务状态
if (isQuestAlreadyCompleted) // 已完成:拒绝并中断后续处理
{
request.Allowed = false; // 标记不允许
request.FailReason = ""; // 写入失败原因
request.StopPropagation = true; // 拦截:不再传给 next
}
}
}
Client
public static class QuestAcceptFlow
{
public static QuestRequest TryAcceptQuest(int playerId, int questId)
{
// 1.组装责任链(顺序很重要)
QuestHandler head = new LevelCheckHandler();
head.SetNext(new QuestStateCheckHandler());
// 2.创建请求对象(携带输入)
var request = new QuestRequest
{
PlayerId = playerId,
QuestId = questId
};
// 3.发起请求,让 request 沿链流转
head.Handle(request);
// 4.返回 request(调用方读取结果)
return request;
}
}
查看7道真题和解析