责任链模式如同aspnetcore中的管道机制,贯穿真个框架的开始和结束。很经典的有请假,写个假条找组长,主管 ,经理,boss等一层一层的去批复,当然每个领导批假的天数是具体明确的,要不然就没法传递下去,这里有两个字很关键,就是“传递”。
下面通过一个简单的计算器的例子具体说明。
public class CalContext { public decimal[] Args { get; set; } public Operator calOperator { get; set; } public decimal Result { get; set; } } public enum Operator { Add, Sub, Mul, Div }
责任链的上下文文本很重要,跟aspnetcore里面的httpcontext一样,起到传递数据承载作用。
public abstract class CalChainBase { private CalChainBase _chainBase; //可以通过可空构造函数,效果一样 public CalChainBase ChainBase { get => _chainBase; set => _chainBase = value; } public abstract CalContext Invoke(CalContext context); }
上面的代码就是整个链子的传递核心所在,依然是抽象功不可没,CalChainBase看起来就是一个对象,但是它确实一类的抽象,正因为这样所以我们可以通过相同的特征对象来不断的替换它,每次替换都可以完成自己的invoke任务,而这个上下文文本CalContext就是整个数据传输的载体。
public class AddChain : CalChainBase { public override CalContext Invoke(CalContext context) { if (context.calOperator.Equals(Operator.Add)) { context.Result = context.Args.Aggregate((x, y) => (x + y)); return context; } if (ChainBase == null) throw new ArgumentNullException(nameof(AddChain)); return ChainBase.Invoke(context); } } public class SubChain : CalChainBase { public override CalContext Invoke(CalContext context) { if (context.calOperator.Equals(Operator.Sub)) { context.Result = context.Args.Aggregate((x, y) => (x - y)); return context; } if (ChainBase == null) throw new ArgumentNullException(nameof(SubChain)); return ChainBase.Invoke(context); } } public class MulChain : CalChainBase { public override CalContext Invoke(CalContext context) { if (context.calOperator.Equals(Operator.Mul)) { context.Result = context.Args.Aggregate((x, y) => (x * y)); return context; } if (ChainBase == null) throw new ArgumentNullException(nameof(MulChain)); return ChainBase.Invoke(context); } } public class DivChain : CalChainBase { public override CalContext Invoke(CalContext context) { if (context.calOperator.Equals(Operator.Div)) { context.Result = context.Args.Aggregate((x, y) => (x / y)); return context; } if (ChainBase == null) throw new ArgumentNullException(nameof(DivChain)); return ChainBase.Invoke(context); } }
上面的实现顺理成章,通过枚举判断具体的实例,面向对象理解好实例(对象)和类之间的关系尤其重要。这个判断就是把本分之内的事情给做了,如果不归我的话那就往下传递。这里可以给一个终结点输出点东西,提示一下context执行完没有被实际处理,这里我省略。
internal class Program { static void Main(string[] args) { CalContext context = new CalContext() { Args = new decimal[] { 1, 2, 3, 4, 5 }, calOperator = Operator.Add }; CalChainBase start = new AddChain(); CalChainBase sub = new SubChain(); CalChainBase mul = new MulChain(); CalChainBase div = new DivChain(); start.ChainBase = sub; sub.ChainBase = mul; mul.ChainBase = div; start.Invoke(context); Console.WriteLine($"+ result= {context.Result}"); context.calOperator = Operator.Sub; start.Invoke(context); Console.WriteLine($"- result= {context.Result}"); context.calOperator = Operator.Mul; start.Invoke(context); Console.WriteLine($"* result= {context.Result}"); context.calOperator = Operator.Div; start.Invoke(context); Console.WriteLine($"/ result= {context.Result}"); context.Args = new decimal[] { 100, 200 }; start.Invoke(context); Console.WriteLine($"/ result= {context.Result}"); } }
上面的客户端实现就顺理成章了,可以在包装一下,这里省略。
总结,责任链也是处理对象与对象之间的关系,只不过它巧妙地把归于抽象类或者接口的一组实现抽象出来CalChainBase这样的模板。
标签:CalChainBase,Invoke,责任,ChainBase,context,public,CalContext From: https://www.cnblogs.com/morec/p/16890533.html