Csharp/C#教程:C#设计模式之职责链模式示例详解分享

前言

   在软件开发中,我们通常会遇到一种场景,比如某个请求,会依次经过系统中的很多个模块来处理,如果某个模块处理不了,则将请求传递给下一个模块,比如在订单处理中,首先要经过用户校验,商品库存充足校验,如果不满足条件,返回错误,如果满足条件才会到下一步处理。

   在ASP.NETCore里有middleware中间键的概念,每一个请求进来,都会经过一系列的Handler,这是一种职责链模式,每一个Handler都会决定是否处理该请求,以及是否决定将该请求传递给一下请求继续处理。

   在.NET的委托中,也有一个委托链概念,当多个对象注册同一事件时,对象将委托放在一个链上,依次处理。

   在JavaScript或者WPF的事件模型中,事件有冒泡和下沉,事件能够逐个向上级或者下级对象传递,每个对象都会决定是否会对该事件进行回应,或者终止事件的继续传递。

   这些都是典型的职责链模式,责任链模式为请求创建了一个接收者对象的链,每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,沿着这条链传递请求,直到有对象处理它为止。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

示例1

假设在一个电脑游戏中,每个角色都有两个属性:攻击值和防御值。

publicclassCreature { publicstringName; publicintAttack,Defense; publicCreature(stringname,intattack,intdefense) { Name=name; Attack=attack; Defense=defense; } publicoverridestringToString() { return$"Name:{Name}Attack:{Attack}Defense:{Defense}"; } }

    现在这个角色会在游戏中进行活动,他可能会捡到一些武器增加自己的攻击值或者防御值。我们通过CreatureModifer来修改该对象的攻击值或者防御值。通常,在游戏中会有多个修改器会对同一角色进行修改,比如捡到武器A,然后捡到武器B等等,因此我们可以将这些修改器按照顺序附加到Creature对象上进行逐个修改。

   在经典的职责链实现模式中,可以向下面这种方式来定义CreatureModifier对象:

publicclassCreatureModifier { protectedCreaturecreature; protectedCreatureModifiernext; publicCreatureModifier(Creaturecreature) { this.creature=creature; } publicvoidAdd(CreatureModifierm) { if(next!=null) { next.Add(m); } else { next=m; } } publicvirtualvoidHandle() { next?.Handle(); } }

   在这个类中:

构造函数里保存对待修改对象Creature的引用。 该类没有做多少工作,但他不是抽象类,其他类可以继承该对象。 Add方法可以添加其他CreatureModifier类到处理链条上。如果当前修改对象next对象为空,则赋值,否则将他添加到处理链的末端。 Handle方法简单调用下个处理链上对象的Handle方法。子类可以重写该方法以实现具体的操作。

   现在,可以定义一个具体的修改类了,这个类可以将角色的攻击值翻倍。

publicclassDoubleAttackModifier:CreatureModifier { publicDoubleAttackModifier(Creaturec):base(c) { } publicoverridevoidHandle() { creature.Attack*=2; Console.WriteLine($"Doubling{creature.Name}'sattack,Attack:{creature.Attack},Defense:{creature.Defense}"); base.Handle(); } }

    该类继承自CreatureModifier类,并重写了Handle方法,在方法里做了两件事,一是将Attack属性翻倍,另外一个非常重要,就是调用了基类的Handle方法,让职责链上的修改器继续进行下去。千万不要忘记调用,否则链条在这里就会终止了,不会继续往下传递了。

    接着,新建一个增加防御值的修改器,如果攻击值小于2,则防御值增加1:

publicclassIncreaseDefenseModifier:CreatureModifier { publicIncreaseDefenseModifier(Creaturecreature):base(creature) { } publicoverridevoidHandle() { if(creature.Attack<=2) { Console.WriteLine($"Increasing{creature.Name}'sdefense"); creature.Defense++; } base.Handle(); } }

    现在整个应用代码如下:

Creaturecreature=newCreature("yy",1,1); Console.WriteLine(creature); CreatureModifiermodi=newCreatureModifier(creature); modi.Add(newDoubleAttackModifier(creature));//attack2,defense1 modi.Add(newDoubleAttackModifier(creature));//attack4,defense1 modi.Add(newIncreaseDefenseModifier(creature));//attack4,defense1 modi.Handle();

   可以看到,第三个IncreaseDefenseModifier因为不满足attack小于等于2的条件,所以Defense没有修改。

示例2

   下面这个例子来自https://refactoring.guru/,首先定义一个包含用来建立处理链的方法,也定义一个处理请求的方法:

publicinterfaceIHandle { IHandleSetNext(IHandlehandle); objectHandle(objectrequest); }

    再定义一个抽象类,用来设置职责链和处理职责链上的请求。

publicabstractclassAbstractHandle:IHandle { privateIHandle_nextHandle; publicIHandleSetNext(IHandlehandle) { this._nextHandle=handle; returnhandle; } publicvirtualobjectHandle(objectrequest) { if(this._nextHandle!=null) { returnthis._nextHandle.Handle(request); } else { returnnull; } } }

    在定义几个具体的职责链上处理的具体类:

publicclassMonkeyHandle:AbstractHandle { publicoverrideobjectHandle(objectrequest) { if(request.ToString()=="Banana") { return$"Monkey:I'lleatthe{request.ToString()}.n"; } else { returnbase.Handle(request); } } } publicclassSquirrelHandler:AbstractHandle { publicoverrideobjectHandle(objectrequest) { if(request.ToString()=="Nut") { return$"Squirrel:I'lleatthe{request.ToString()}.n"; } else { returnbase.Handle(request); } } } publicclassDogHandler:AbstractHandle { publicoverrideobjectHandle(objectrequest) { if(request.ToString()=="MeatBall") { return$"Dog:I'lleatthe{request.ToString()}.n"; } else { returnbase.Handle(request); } } }

   再定义使用方法,参数为单个职责链参数:

publicstaticvoidClientCode(AbstractHandlerhandler) { foreach(varfoodinnewList<string>{"Nut","Banana","Cupofcoffee"}) { Console.WriteLine($"Client:Whowantsa{food}?"); varresult=handler.Handle(food); if(result!=null) { Console.Write($"{result}"); } else { Console.WriteLine($"{food}wasleftuntouched."); } } }

    现在定义流程处理链:

//Theotherpartoftheclientcodeconstructstheactualchain. varmonkey=newMonkeyHandler(); varsquirrel=newSquirrelHandler(); vardog=newDogHandler(); monkey.SetNext(squirrel).SetNext(dog); //Theclientshouldbeabletosendarequesttoanyhandler,not //justthefirstoneinthechain. Console.WriteLine("Chain:Monkey>Squirrel>Dogn"); ClientCode(monkey); Console.WriteLine(); Console.WriteLine("Subchain:Squirrel>Dogn"); ClientCode(squirrel);

   输出结果为:

Chain:Monkey>Squirrel>Dog

Client:WhowantsaNut?
  Squirrel:I’lleattheNut.
Client:WhowantsaBanana?
  Monkey:I’lleattheBanana.
Client:WhowantsaCupofcoffee?
  Cupofcoffeewasleftuntouched.

Subchain:Squirrel>Dog

Client:WhowantsaNut?
  Squirrel:I’lleattheNut.
Client:WhowantsaBanana?
  Bananawasleftuntouched.
Client:WhowantsaCupofcoffee?
  Cupofcoffeewasleftuntouched.

上述就是C#学习教程:C#设计模式之职责链模式示例详解分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/903557.html

(0)
上一篇 2021年10月21日
下一篇 2021年10月21日

精彩推荐