前置文章: 设计模式的原则
其他设计模式:用心理解设计模式
设计模式相关代码已统一放至 我的 Github
一、定义
行为型模式之一。
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
(通过给予多个对象处理请求的机会,来避免请求的发送方与接收方之间的耦合。将接收对象链起来,并沿着链传递请求,直到有对象处理它为止。)
二、结构解析
责任链模式的一般结构有两种角色: 抽象处理者、具体处理者。
抽象处理者(Handler):定义一个处理请求的接口方法,并持有一个后继责任对象(另一个处理者)。当这个接口方法被调用,并且自身不能处理时,调用后继责任对象中同样的接口方法,使得请求可以向更高的位置传递。一般可以将这个接口方法定义为 模板方法确定责任传递规则,同时为具体处理者出一个抽象的接口,让具体处理者实现自身的请求处理功能。
具体处理者(ConcreteHandler):继承抽象处理者,实现自身的请求处理功能。
三、评价
责任链模式让每个(最后一个没有)处理者持有另一个后继处理者,众多处理者形成了一个处理链。让请求在这个链上传递,执行时就像一个 “if, elseif..., else” 语句执行一样。
责任链模式中各处理者常存在等级或权限元素(可能是潜在的),条件判断与这个元素密切相关。如审批流。
责任链模式解除了请求发送者和接收者的耦合,使请求发送者不用依赖每一个接收者,想要增加请求接收者也很容易。
应避免出现闭环链,否则可能将形成死循环(虽然闭环,但实际执行不超过一圈的,也不会死循环)。
四、实现
using UnityEngine;
namespace ChainOfResponsibility
{
//抽象处理器
public abstract class Handler
{
public string name; //名称
public int level; //自身等级
public Handler successor; //持有一个后继责任对象(另一个处理器)
public Handler(string name, int level, Handler successor = null)
{
this.name = name;
this.level = level;
this.successor = successor;
}
//定义一个模板方法,确定责任传递规则,约定一个条件,满足条件时自己处理,否则交给后继者处理。
public void HandleRequest(int needLevel)
{
if (level >= needLevel) //处理者等级大于等于请求要求的等级时,才可处理
{
this.HandleImp();
}
else
{
if (successor != null)
{
//交给后继者处理。
successor.HandleRequest(needLevel);
}
else
{
//注意,这里要处理好,无后继者时的情况。
//如,只好勉强自己处理。
this.HandleImp();
}
}
}
public abstract void HandleImp();
}
//具体处理器
public class ConcreteHandler : Handler
{
public ConcreteHandler(string name, int level, Handler successor = null) : base(name, level, successor) { }
public override void HandleImp()
{
Debug.Log("我来处理请求,我是: " + this.name);
}
}
public class Client
{
static public void Main()
{
//组装责任链
Handler handlerA = new ConcreteHandler("ConcreteHandlerA", 9);
Handler handlerB = new ConcreteHandler("ConcreteHandlerB", 3, handlerA);
Handler handlerC = new ConcreteHandler("ConcreteHandlerC", 2, handlerB);
Handler handlerD = new ConcreteHandler("ConcreteHandlerD", 1, handlerC);
handlerD.HandleRequest(1); //请求要求等级为1时,D就可以处理
handlerD.HandleRequest(5); //请求要求等级为5时,A才能处理
}
}
}