一、概述
顾名思义,管道模式就像一条管道把多个对象连接起来,整体看起来就像若干个阀门嵌套在管道中,而处理逻辑就放在阀门上,如下图,需要处理的对象进入管道后,分别经过阀门一、阀门二、阀门三、阀门四,每个阀门都会对进入的对象进行一些逻辑处理,经过一层层的处理后从管道尾处理,此时的对象就是已完成处理的目标对象。
二、主要角色
- 阀门 处理数据的节点
- 管道 组织各个阀门
- 客户端 构造管道,并调用
三、实现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,它持有一个头阀门和一个尾阀门,它按照添加阀门顺序的方式构造阀门链表,按照队列的形式,先添加的先调用。