最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#設(shè)計(jì)模式之職責(zé)鏈模式示例詳解

 更新時(shí)間:2020年12月20日 08:42:19   作者:yangyang  
這篇文章主要給大家介紹了關(guān)于C#設(shè)計(jì)模式之職責(zé)鏈模式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

    在軟件開發(fā)中,我們通常會(huì)遇到一種場(chǎng)景,比如某個(gè)請(qǐng)求,會(huì)依次經(jīng)過(guò)系統(tǒng)中的很多個(gè)模塊來(lái)處理,如果某個(gè)模塊處理不了,則將請(qǐng)求傳遞給下一個(gè)模塊,比如在訂單處理中,首先要經(jīng)過(guò)用戶校驗(yàn),商品庫(kù)存充足校驗(yàn),如果不滿足條件,返回錯(cuò)誤,如果滿足條件才會(huì)到下一步處理。

    在ASP.NET Core里有middleware中間鍵的概念,每一個(gè)請(qǐng)求進(jìn)來(lái),都會(huì)經(jīng)過(guò)一系列的Handler,這是一種職責(zé)鏈模式,每一個(gè)Handler都會(huì)決定是否處理該請(qǐng)求,以及是否決定將該請(qǐng)求傳遞給一下請(qǐng)求繼續(xù)處理。

    在.NET的委托中,也有一個(gè)委托鏈概念,當(dāng)多個(gè)對(duì)象注冊(cè)同一事件時(shí),對(duì)象將委托放在一個(gè)鏈上,依次處理。

    在JavaScript或者WPF的事件模型中,事件有冒泡和下沉,事件能夠逐個(gè)向上級(jí)或者下級(jí)對(duì)象傳遞,每個(gè)對(duì)象都會(huì)決定是否會(huì)對(duì)該事件進(jìn)行回應(yīng),或者終止事件的繼續(xù)傳遞。

    這些都是典型的職責(zé)鏈模式,責(zé)任鏈模式為請(qǐng)求創(chuàng)建了一個(gè)接收者對(duì)象的鏈,每個(gè)接收者都包含對(duì)另一個(gè)接收者的引用。如果一個(gè)對(duì)象不能處理該請(qǐng)求,那么它會(huì)把相同的請(qǐng)求傳給下一個(gè)接收者,沿著這條鏈傳遞請(qǐng)求,直到有對(duì)象處理它為止。發(fā)出這個(gè)請(qǐng)求的客戶端并不知道鏈上的哪一個(gè)對(duì)象最終處理這個(gè)請(qǐng)求,這使得系統(tǒng)可以在不影響客戶端的情況下動(dòng)態(tài)地重新組織和分配責(zé)任。

示例1

假設(shè)在一個(gè)電腦游戲中,每個(gè)角色都有兩個(gè)屬性:攻擊值和防御值。

public class Creature
{
 public string Name;
 public int Attack, Defense;
 public Creature(string name, int attack, int defense)
 {
 Name = name;
 Attack = attack;
 Defense = defense;
 }

 public override string ToString()
 {
 return $"Name:{Name} Attack:{Attack} Defense:{Defense}";
 }
}

     現(xiàn)在這個(gè)角色會(huì)在游戲中進(jìn)行活動(dòng),他可能會(huì)撿到一些武器增加自己的攻擊值或者防御值。我們通過(guò)CreatureModifer來(lái)修改該對(duì)象的攻擊值或者防御值。通常,在游戲中會(huì)有多個(gè)修改器會(huì)對(duì)同一角色進(jìn)行修改,比如撿到武器A,然后撿到武器B等等,因此我們可以將這些修改器按照順序附加到Creature對(duì)象上進(jìn)行逐個(gè)修改。

    在經(jīng)典的職責(zé)鏈實(shí)現(xiàn)模式中,可以向下面這種方式來(lái)定義CreatureModifier對(duì)象:

public class CreatureModifier
{
 protected Creature creature;
 protected CreatureModifier next;
 public CreatureModifier(Creature creature)
 {
 this.creature = creature;
 }
 public void Add(CreatureModifier m)
 {
 if (next != null)
 {
 next.Add(m);
 }
 else
 {
 next = m;
 }
 }
 public virtual void Handle()
 {
 next?.Handle();
 }
}

    在這個(gè)類中:

  • 構(gòu)造函數(shù)里保存對(duì)待修改對(duì)象Creature的引用。
  • 該類沒(méi)有做多少工作,但他不是抽象類,其他類可以繼承該對(duì)象。
  • Add方法可以添加其他CreatureModifier類到處理鏈條上。如果當(dāng)前修改對(duì)象next對(duì)象為空,則賦值,否則將他添加到處理鏈的末端。
  • Handle方法簡(jiǎn)單調(diào)用下個(gè)處理鏈上對(duì)象的Handle方法。子類可以重寫該方法以實(shí)現(xiàn)具體的操作。

    現(xiàn)在,可以定義一個(gè)具體的修改類了,這個(gè)類可以將角色的攻擊值翻倍。

public class DoubleAttackModifier : CreatureModifier
{
 public DoubleAttackModifier(Creature c) : base(c)
 {
 }

 public override void Handle()
 {
 creature.Attack *= 2;
 Console.WriteLine($"Doubling {creature.Name}'s attack,Attack:{creature.Attack},Defense:{creature.Defense}");
 base.Handle();
 }
}

     該類繼承自CreatureModifier類,并重寫了Handle方法,在方法里做了兩件事,一是將Attack屬性翻倍,另外一個(gè)非常重要,就是調(diào)用了基類的Handle方法,讓職責(zé)鏈上的修改器繼續(xù)進(jìn)行下去。千萬(wàn)不要忘記調(diào)用,否則鏈條在這里就會(huì)終止了,不會(huì)繼續(xù)往下傳遞了。

     接著,新建一個(gè)增加防御值的修改器,如果攻擊值小于2,則防御值增加1:

public class IncreaseDefenseModifier : CreatureModifier
{
 public IncreaseDefenseModifier(Creature creature) : base(creature)
 {
 }
 public override void Handle()
 {
 if (creature.Attack <= 2)
 {
 Console.WriteLine($"Increasing {creature.Name}'s defense");
 creature.Defense++;
 }
 base.Handle();
 }
}

     現(xiàn)在整個(gè)應(yīng)用代碼如下:

Creature creature = new Creature("yy", 1, 1);
Console.WriteLine(creature);
CreatureModifier modi = new CreatureModifier(creature);
modi.Add(new DoubleAttackModifier(creature));//attack 2,defense 1
modi.Add(new DoubleAttackModifier(creature));//attack 4,defense 1
modi.Add(new IncreaseDefenseModifier(creature));//attack 4,defense 1
modi.Handle();

    可以看到,第三個(gè)IncreaseDefenseModifier因?yàn)椴粷M足attack小于等于2的條件,所以Defense沒(méi)有修改。

示例2

    下面這個(gè)例子來(lái)自 https://refactoring.guru/ ,首先定義一個(gè)包含用來(lái)建立處理鏈的方法,也定義一個(gè)處理請(qǐng)求的方法:

public interface IHandle
{
 IHandle SetNext(IHandle handle);
 object Handle(object request);
}

     再定義一個(gè)抽象類,用來(lái)設(shè)置職責(zé)鏈和處理職責(zé)鏈上的請(qǐng)求。

public abstract class AbstractHandle : IHandle
{
 private IHandle _nextHandle;

 public IHandle SetNext(IHandle handle)
 {
 this._nextHandle = handle;
 return handle;
 }

 public virtual object Handle(object request)
 {
 if (this._nextHandle != null)
 {
 return this._nextHandle.Handle(request);
 }
 else
 {
 return null;
 }
 }
}

     在定義幾個(gè)具體的職責(zé)鏈上處理的具體類:

public class MonkeyHandle : AbstractHandle
{
 public override object Handle(object request)
 {
 if (request.ToString() == "Banana")
 {
  return $"Monkey: I'll eat the {request.ToString()}.\n";
 }
 else
 {
  return base.Handle(request);
 }
 }
}

public class SquirrelHandler : AbstractHandle
{
 public override object Handle(object request)
 {
 if (request.ToString() == "Nut")
 {
  return $"Squirrel: I'll eat the {request.ToString()}.\n";
 }
 else
 {
  return base.Handle(request);
 }
 }
}

public class DogHandler : AbstractHandle
{
 public override object Handle(object request)
 {
 if (request.ToString() == "MeatBall")
 {
  return $"Dog: I'll eat the {request.ToString()}.\n";
 }
 else
 {
  return base.Handle(request);
 }
 }
}

    再定義使用方法,參數(shù)為單個(gè)職責(zé)鏈參數(shù):

public static void ClientCode(AbstractHandler handler)
{
 foreach (var food in new List<string> { "Nut", "Banana", "Cup of coffee" })
 {
 Console.WriteLine($"Client: Who wants a {food}?");

 var result = handler.Handle(food);

 if (result != null)
 {
  Console.Write($" {result}");
 }
 else
 {
  Console.WriteLine($" {food} was left untouched.");
 }
 }
}

     現(xiàn)在定義流程處理鏈:

// The other part of the client code constructs the actual chain.
var monkey = new MonkeyHandler();
var squirrel = new SquirrelHandler();
var dog = new DogHandler();

monkey.SetNext(squirrel).SetNext(dog);

// The client should be able to send a request to any handler, not
// just the first one in the chain.
Console.WriteLine("Chain: Monkey > Squirrel > Dog\n");
ClientCode(monkey);
Console.WriteLine();

Console.WriteLine("Subchain: Squirrel > Dog\n");
ClientCode(squirrel);

    輸出結(jié)果為:

Chain: Monkey > Squirrel > Dog

Client: Who wants a Nut?
   Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
   Monkey: I'll eat the Banana.
Client: Who wants a Cup of coffee?
   Cup of coffee was left untouched.

Subchain: Squirrel > Dog

Client: Who wants a Nut?
   Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
   Banana was left untouched.
Client: Who wants a Cup of coffee?
   Cup of coffee was left untouched.

總結(jié)

    職責(zé)鏈模式是一個(gè)很簡(jiǎn)單的設(shè)計(jì)模式,在需要順序處理請(qǐng)求比如命令或查詢時(shí),可以使用該模式。最簡(jiǎn)單的實(shí)現(xiàn)方式就是每個(gè)對(duì)象引用下一個(gè)待處理的對(duì)象,可以使用一個(gè)List或者LinkList來(lái)實(shí)現(xiàn)。

    到此這篇關(guān)于C#設(shè)計(jì)模式之職責(zé)鏈模式的文章就介紹到這了,更多相關(guān)C#設(shè)計(jì)模式之職責(zé)鏈模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

參考

https://refactoring.guru/design-patterns/chain-of-responsibility

https://stackoverflow.com/questions/48851112/is-the-chain-of-responsibility-used-in-the-net-framework

m.fzitv.net/article/202503.htm 

相關(guān)文章

  • C#調(diào)用dos窗口獲取相關(guān)信息的方法

    C#調(diào)用dos窗口獲取相關(guān)信息的方法

    這篇文章主要介紹了C#調(diào)用dos窗口獲取相關(guān)信息的方法,涉及C#調(diào)用dos窗口及進(jìn)程操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-08-08
  • C#實(shí)現(xiàn)PDF文件添加圖片背景

    C#實(shí)現(xiàn)PDF文件添加圖片背景

    這篇文章主要介紹了C#實(shí)現(xiàn)PDF文件添加圖片背景的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • C# Request.Form用法案例詳解

    C# Request.Form用法案例詳解

    這篇文章主要介紹了C# Request.Form用法案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C# 并行和多線程編程——Task進(jìn)階知識(shí)

    C# 并行和多線程編程——Task進(jìn)階知識(shí)

    這篇文章主要介紹了C# 并行和多線程編程——Task進(jìn)階知識(shí)的的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-02-02
  • 基于StreamRead和StreamWriter的使用(實(shí)例講解)

    基于StreamRead和StreamWriter的使用(實(shí)例講解)

    下面小編就為大家分享一篇基于StreamRead和StreamWriter的使用實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • C#將文件復(fù)制到指定文件夾并整理

    C#將文件復(fù)制到指定文件夾并整理

    這篇文章主要介紹了C#將文件復(fù)制到指定文件夾并按照時(shí)間順序來(lái)整理歸檔的方法,另外附上其他網(wǎng)友的2種實(shí)現(xiàn)方式,有需要的小伙伴可以參考下。
    2015-06-06
  • C#中DataBindings用法實(shí)例分析

    C#中DataBindings用法實(shí)例分析

    這篇文章主要介紹了C#中DataBindings用法,結(jié)合實(shí)例形式詳細(xì)分析了DataBindings綁定數(shù)據(jù)源及刷新數(shù)據(jù)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • C#繪制時(shí)鐘的方法

    C#繪制時(shí)鐘的方法

    這篇文章主要為大家詳細(xì)介紹了C#繪制時(shí)鐘的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C# using語(yǔ)法糖圖文詳解

    C# using語(yǔ)法糖圖文詳解

    這篇文章主要給大家介紹了關(guān)于C# using語(yǔ)法糖的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 在C#中如何使用正式表達(dá)式獲取匹配所需數(shù)據(jù)

    在C#中如何使用正式表達(dá)式獲取匹配所需數(shù)據(jù)

    本文給大家分享C#中如何使用正式表達(dá)式獲取匹配所需數(shù)據(jù) ,非常實(shí)用,對(duì)正則表達(dá)式獲取匹配相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2016-03-03

最新評(píng)論

颍上县| 闵行区| 黄骅市| 太康县| 盐津县| 景泰县| 濉溪县| 化德县| 宣城市| 阿坝县| 高尔夫| 石景山区| 绿春县| 抚宁县| 朝阳县| 长顺县| 德州市| 平凉市| SHOW| 大同市| 孝义市| 东乡| 富裕县| 融水| 潞城市| 嵩明县| 惠州市| 永仁县| 兰考县| 鹿泉市| 昌图县| 綦江县| 利辛县| 蒙自县| 公安县| 黄冈市| 渭源县| 思南县| 龙岩市| 古蔺县| 柳河县|