这次和大家一起学习一下 职责链设计模式。职责链设计模式非常好用,尤其是在做逻辑判断处理很多的情况下,比如一些AI的设计,配合FSM状态机可以做到一个入门级AI的小机器人。后面就用cs的ai敌人来大概讲解下职责链模式的用法。首先我们来看下职责链示例的代码:
/// <summary>
/// Handler类 定义一个处理请示的接口
/// </summary>
abstract class Handler
{
protected Handler successor;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(int request);
}
class ConcreteHandler1 : Handler //一级处理 处理0到10
{
public override void HandleRequest(int request)
{
if (request >= 0 && request <= 10) //处理自己能力或者职责范围内的事情
{
Console.WriteLine(this.GetType().Name + "处理请求" + request);
}
else if (successor != null) //扛不住了 如果有老大 丢给老大处理
{
successor.HandleRequest(request);
}
}
}
class ConcreteHandler2 : Handler //二级处理 处理10到20之间
{
public override void HandleRequest(int request)
{
if (request >= 10 && request < 20)
{
Console.WriteLine(this.GetType().Name + "处理请求" + request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
class ConcreteHandler3 : Handler //三级处理 处理20到30之间
{
public override void HandleRequest(int request)
{
if (request >= 20 && request < 30)
{
Console.WriteLine(this.GetType().Name + "处理请求" + request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
我们先声明了一个Handler 接口, 里面还包含了一个和自己一样的类,作为下一级处理程序 还有一个HandleRequest 方法,用来代表自己要处理逻辑的方法, 然后和三个实体类都继承了Handler 接口,分别是小中大 三个处理程序,小处理0到10数字,中处理11到20,大的处理21到30 ,现在到Main方法看看。
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
int[] requests = { 2, 5, 16, 22, 18, 3, 24, 56 };
foreach (int request in requests)
{
h1.HandleRequest(request);
}
Console.ReadKey();
我们new 3个实体类,h2作为h1的下级处理程序,h3作为h2的下级处理程序。然后用循环把 数组的数字传入h1的处理方法。
运行结果如下:
每个实体类就很好的处理了自己该做的逻辑处理,而不会处理的就转移到下一层给其他逻辑处理去了。好了,原理大概就是这样,那现在我们来试试做个简单的cs的AI敌人逻辑看看,我们的AI敌人分为几段距离来做不同的反应,首先我们先声明一个距离处理模块,然后是一个近处距离处理类,和一个远处距离处理类。
/// <summary>
/// 距离处理模块
/// </summary>
abstract class DistanceHandler
{
protected DistanceHandler successor;
public void SetSuccessor(DistanceHandler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(int distance);
}
/// <summary>
/// 近处处理 处理近处战斗处理
/// </summary>
class NearHandler : DistanceHandler
{
public override void HandleRequest(int distance)
{
if (distance >= 0 && distance <= 2) //处理自己能力或者职责范围内的事情
{
Console.WriteLine(this.GetType().Name + "处理距离:" + distance+"的敌人使用匕首攻击");
}
else if (distance >= 2 && distance <= 10)
{
Console.WriteLine(this.GetType().Name + "处理距离:" + distance + "的敌人使用手枪攻击");
}
else //距离过远
{
if (successor != null) //如果有其他处理就让它接盘
{
successor.HandleRequest(distance);
}
else //距离太远 又没人接盘 那就赶紧逃跑吧
{
Console.WriteLine("打不过,赶紧跑");
}
}
}
}
/// <summary>
/// 远处处理 处理远处战斗处理
/// </summary>
class FarHandler : DistanceHandler
{
public override void HandleRequest(int distance)
{
if (distance >= 10 && distance <= 100)
{
Console.WriteLine(this.GetType().Name + "处理距离:" + distance + "的敌人使用主武器攻击");
}
else if (distance >= 100 && distance <= 300)
{
Console.WriteLine(this.GetType().Name + "处理距离:" + distance + "的敌人,如果没有狙击枪就躲起来守株待兔");
}
else //距离过远
{
if (successor != null) //如果有其他处理就让它接盘
{
successor.HandleRequest(distance);
}
else //距离太远 又没人接盘
{
Console.WriteLine("这么远,还是找别人打好了");
}
}
}
}
我们在近处判断,如果距离低于2米就使用匕首武器,(实际情况下 匕首武器也可以弄成一个二级类,从这一块跳转到匕首武器类的处理方法去)10米内就使用手枪武器(同上),如果距离太远,当前处理不过来,就给下一级处理,下一级就是远处战斗类。然后我们在Main方法看看:
DistanceHandler near = new NearHandler();
FarHandler far = new FarHandler();
near.SetSuccessor(far); //近处战斗处理下层处理设置为远处战斗
int[] disList = { 2, 4, 76, 34, 27, 49, 15, 456, 133 };
foreach (int dis in disList)
{
near.HandleRequest(dis);
}
Console.ReadKey();
我们声明了一个far 和near类。让far作为near的下级处理程序,下面声明disList 的数组,模拟敌人要处理的距离,然后在foreach循环传入。最后我们看看结果:
好了,职责链模式的用法就介绍到这里了,后面我们再来回顾下职责链模式 职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。职责链的好处就是使得接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构,结果是职责链可简化对象的互相连接,他们仅需保持一个指向其后继者的引用,而不需保持它的所有的候选接受者的引用,从而大大降低了耦合度。我们就可以随时增加或者修改一个请求的结构,增强了给对象指派职责的灵活性。