一、概述
顧名思義,管道模式就像一條管道把多個對象連接起來,整體看起來就像若干個閥門嵌套在管道中,而處理邏輯就放在閥門上,如下圖,需要處理的對象進入管道后,分別經過閥門一、閥門二、閥門三、閥門四,每個閥門都會對進入的對象進行一些邏輯處理,經過一層層的處理后從管道尾處理,此時的對象就是已完成處理的目標對象。
二、主要角色
- 閥門 處理數據的節點
- 管道 組織各個閥門
- 客戶端 構造管道,並調用
三、實現Demo
using System; /// <summary> ///PipeLine模式的幾個角色 ///閥門 處理數據的節點 ///管道 組織各個閥門 ///客戶端 構造管道,並調用 /// </summary> namespace DesignMode_PileLine { //閥門接口 public interface IValve { IValve GetNext(); void SetNext(IValve v); void Invoke(string s); } //管道接口 public interface IPipeLine { IValve GetFirst(); IValve GetBasic(); void SetBasic(IValve v); void AddValve(IValve v); } /// <summary> ///尾閥門 /// </summary> public class BasicValve:IValve { private IValve _nextValve; public IValve GetNext() { return _nextValve; } public void SetNext(IValve v) { _nextValve = v; } public void Invoke(string s) { string org = s; Console.WriteLine($"Basic valve invoked! Will replace a with b"); s = s.Replace('a', 'b'); Console.WriteLine($"Basic valved handled: {org} => {s}"); } } /// <summary> /// 普通閥門 /// </summary> /// public class FirstValve : IValve { private IValve _nextValve; public IValve GetNext() { return _nextValve; } public void SetNext(IValve v) { _nextValve = v; } public void Invoke(string s) { string org = s; Console.WriteLine($"First valve invoked! Will replace 1 with 2"); s = s.Replace('1', '2'); Console.WriteLine($"First valved handled: {org} => {s}"); GetNext()?.Invoke(s);//將數據傳遞到下一個閥門 } } public class SecondValve : IValve { private IValve _nextValve; public IValve GetNext() { return _nextValve; } public void SetNext(IValve v) { _nextValve = v; } public void Invoke(string s) { string org = s; Console.WriteLine($"Second valve invoked! Will replace 5 with 6"); s = s.Replace('5', '6'); Console.WriteLine($"Second valved handled: {org} => {s}"); GetNext()?.Invoke(s);//將數據傳遞到下一個閥門 } } public class StandardPipeLine :IPipeLine { private IValve _firstValve; private IValve _basicValve; public IValve GetFirst() { return _firstValve; } public IValve GetBasic() { return _basicValve; } public void SetBasic(IValve v) { _basicValve = v; } public void AddValve(IValve v) { if(_firstValve == null) { _firstValve = v; v.SetNext(_basicValve); } else { IValve current = _firstValve; while(current != null) { if (current.GetNext() == _basicValve) { current.SetNext(v); v.SetNext(_basicValve); break; } current = current.GetNext(); } } } } class Program { static void Main(string[] args) { string s = "1123wsa346yt4543s2156ac"; StandardPipeLine pipeLine = new StandardPipeLine(); BasicValve basicValve = new BasicValve(); FirstValve firstValve = new FirstValve(); SecondValve secondValve = new SecondValve(); pipeLine.SetBasic(basicValve); pipeLine.AddValve(firstValve); pipeLine.AddValve(secondValve); pipeLine.GetFirst().Invoke(s); } } }
注:
閥門的實現分兩種,即普通閥門和尾閥門。普通閥門在處理完自己的事情之后,必須調用GetNext.invoke(s)方法交給下一個閥門處理;而尾閥門不用調用這個方法,因為它是結束的那個閥門。
PipeLine實現類的主要邏輯在AddValve,它持有一個頭閥門和一個尾閥門,它按照添加閥門順序的方式構造閥門鏈表,按照隊列的形式,先添加的先調用。