学习链接:
行为型模式之责任链模式 - 二次元攻城狮 - 博客园 (cnblogs.com)
正文
首先,我们要搞清楚责任链模式的结构及其目的。
结构很简单,责任链模式下,事件的处理分为事件发起者和事件处理者,事件处理者是多个处理者的集合,此集合的节点之间成链式关系(节点与节点之间相连)。责任链模式的用于在于讲事件发起者和处理者以及处理逻辑高度解耦,按照以往的逻辑,事件发起者独自处理事件的时候,如果需要写一个统一的数据接口,就需要撰写大量的if else进行数据类型判断然后根据数据类型来处理。
很明显,大量的if else就是设计模式的处理对象之一。
下面是一段简单的C# 责任链模式代码。
public enum HandlerType
{
floatHandler,stringHandler
}
#region 抽象基类
//抽象基类
public abstract class Handler
{
private Handler next;
public void SetNext(Handler next)
{
this.next = next;
}
public virtual void Set(HandlerType handlerType,ref HandlerStruct value)
{
if(GetHandlerType() == handlerType)
{
HandlerRequest(ref value);
}
else
{
next.Set(handlerType,ref value);
}
}
protected abstract void HandlerRequest(ref HandlerStruct value);
public abstract HandlerType GetHandlerType();
}
#endregion
public struct HandlerStruct
{
Object objValue;
Type type;
public HandlerStruct(Type type,object objValue)
{
this.objValue = objValue;
this.type = type;
}
public T? GetValue<T>() where T : class
{
if(objValue is null || type is null || typeof(T) != type)
{
return null;
}
return objValue as T;
}
}
#region 具体处理类
//具体处理类
public class FloatHandler : Handler
{
protected override void HandlerRequest(ref HandlerStruct value)
{
Console.WriteLine($"floatHandler:{value.GetValue<FloatModel>()}");
}
public override HandlerType GetHandlerType()
{
return HandlerType.floatHandler;
}
public class FloatModel
{
public float value;
public FloatModel(float value)
{
this.value = value;
}
public override string ToString()
{
return value.ToString();
}
}
}
public class StringHandler : Handler
{
protected override void HandlerRequest(ref HandlerStruct value)
{
Console.WriteLine($"stringHandler{value.GetValue<string>()}");
}
public override HandlerType GetHandlerType()
{
return HandlerType.stringHandler;
}
}
#endregion
//处理中心
public static class HandlerCenter
{
private static List<Handler> mHandlers = new List<Handler>();
static HandlerCenter()
{
mHandlers.Add(new FloatHandler());
mHandlers.Add(new StringHandler());
}
private static void Init()
{
if(mHandlers.Count < 2)
{
return;
}
//单链式责任链
for(int i = 0 ; i < mHandlers.Count-1 ; i++)
{
mHandlers[i].SetNext(mHandlers[i+1]);
}
}
public static void Add(Handler handler)
{
if(mHandlers.Find(handler1 => handler1.GetHandlerType() == handler.GetHandlerType()) != null)
return;
mHandlers.Add(handler);
Init();
}
public static void Remove(int index)
{
mHandlers.Remove(mHandlers[index]);
Init();
}
//责任链入口
public static void Execute(HandlerType handlerType, ref HandlerStruct value)
{
if(mHandlers.Count <= 0)
{
return;
}
mHandlers[0].Set(handlerType,ref value);
}
}
首先,我们定义一个抽象类作为所有处理节点的基类,并且在此处我们使用模板方法,隐藏部分不可见逻辑,公开部分可见逻辑。
public abstract class Handler
{
private Handler next;
public void SetNext(Handler next)
{
this.next = next;
}
public virtual void Set(HandlerType handlerType,ref HandlerStruct value)
{
if(GetHandlerType() == handlerType)
{
HandlerRequest(ref value);
}
else if(next != null)
{
next.Set(handlerType,ref value);
}
}
protected abstract void HandlerRequest(ref HandlerStruct value);
public abstract HandlerType GetHandlerType();
}
protected abstract void HandlerRequest(ref HandlerStruct value);
此段代码便是核心处理代码,抽象方法让子类去实现核心逻辑
public abstract HandlerType GetHandlerType();
此段代码是为了记录子类的处理数据特征,Set()函数会根据数据判断数据是否为可处理的。
可以处理则交给HandlerRequest(),如果不行,就抛给next节点(next节点不为空下)
以下为继承Handler的示例处理节点
FloatHandler.cs
public class FloatHandler : Handler
{
protected override void HandlerRequest(ref HandlerStruct value)
{
Console.WriteLine($"floatHandler:{value.GetValue<FloatModel>()}");
}
public override HandlerType GetHandlerType()
{
return HandlerType.floatHandler;
}
public class FloatModel
{
public float value;
public FloatModel(float value)
{
this.value = value;
}
public override string ToString()
{
return value.ToString();
}
}
}
StringHandler.cs
public class StringHandler : Handler
{
protected override void HandlerRequest(ref HandlerStruct value)
{
Console.WriteLine($"stringHandler{value.GetValue<string>()}");
}
public override HandlerType GetHandlerType()
{
return HandlerType.stringHandler;
}
}
然后就是一个静态处理中心,用于统一接收数据,当然,这里只是测试,实际业务逻辑需要按照业务情况来定义,比如单例或者其他情况
HandlerCenter.cs
//处理中心
public static class HandlerCenter
{
private static List<Handler> mHandlers = new List<Handler>();
static HandlerCenter()
{
mHandlers.Add(new FloatHandler());
mHandlers.Add(new StringHandler());
}
private static void Init()
{
if(mHandlers.Count < 2)
{
return;
}
//单链式责任链
for(int i = 0 ; i < mHandlers.Count-1 ; i++)
{
mHandlers[i].SetNext(mHandlers[i+1]);
}
}
public static void Add(Handler handler)
{
if(mHandlers.Find(handler1 => handler1.GetHandlerType() == handler.GetHandlerType()) != null)
return;
mHandlers.Add(handler);
Init();
}
public static void Remove(int index)
{
mHandlers.Remove(mHandlers[index]);
Init();
}
//责任链入口
public static void Execute(HandlerType handlerType, ref HandlerStruct value)
{
if(mHandlers.Count <= 0)
{
return;
}
mHandlers[0].Set(handlerType,ref value);
}
}
(注意,这只是示例代码,实际上,因为我定义了Enum枚举变量作为数据特征,然后我还将处理节点存在了list里,所以我完全可以直接通过list查找符合特征的节点然后使用就行)
此处,我只是单纯的将两个节点按照顺序链接,形成一个单链表。
实际上我们可以使用更复杂的处理逻辑,因为如果处理节点过多,单链表从头开始遍历效率会大打折扣。
此外,根据学习链接的文章所示,责任链模式细分两种模式,一种就是目前这种单链完全责任模式,由一个节点完全处理所有数据,一种就是不完全责任链模式,一个节点只负责一个一部分,剩下的传给下一个节点,笔者个人认为,后者有一点像工厂流水线,适合和工厂模式结合使用,多人开发下,效率更高。
如下示例,我写了三个节点,
ImperfectHandler、ImperfectHandlerStr、ImperfectHandlerInt
和一个ImperfectModel类作为数据模板转递信息。
public class ImperfectHandler : Handler
{
protected override void HandlerRequest(ref HandlerStruct value)
{
new ImperfectHandlerStr().Set(HandlerType.ImperfectHandler,ref value);
Console.WriteLine(value.GetValue<ImperfectModel>()?.strValue);
new ImperfectHandlerInt().Set(HandlerType.ImperfectHandler,ref value);
Console.WriteLine(value.GetValue<ImperfectModel>()?.strValue);
}
public override HandlerType GetHandlerType()
{
return HandlerType.ImperfectHandler;
}
public class ImperfectModel
{
public string strValue;
public float intValue;
}
}
namespace Test
{
public partial class ImperfectHandlerStr
{
}
public partial class ImperfectHandlerInt
{
}
}
namespace Test
{
public partial class ImperfectHandlerStr : Handler
{
protected override void HandlerRequest(ref HandlerStruct value)
{
ImperfectHandler.ImperfectModel? model = value.GetValue<ImperfectHandler.ImperfectModel>();
model.strValue = "Handler:"+model.intValue;
}
public override HandlerType GetHandlerType()
{
return HandlerType.ImperfectHandler;
}
}
public partial class ImperfectHandlerInt : Handler
{
protected override void HandlerRequest(ref HandlerStruct value)
{
ImperfectHandler.ImperfectModel? model = value.GetValue<ImperfectHandler.ImperfectModel>();
model.intValue ++;
new ImperfectHandlerStr().Set( HandlerType.ImperfectHandler ,ref value);
}
public override HandlerType GetHandlerType()
{
return HandlerType.ImperfectHandler;
}
}
}
ImperfectHandler作为头节点,也就是责任链入口,它会依次实例化ImperfectHandlerStr和ImperfectHandlerInt并使用这两个节点分别处理ImperfectModel中的部分数据。
并且,ImperfectHandlerInt中又再次调用了ImperfectHandlerStr来处理字符串
效果如图。