本文用到的編程語言為C#,具體思路不限制編程語言。
剛才正在浏覽http://ruby-china.org/topics/7384的時候,看到5樓的回復,突然有一種想法,不知道優劣,請大家幫忙評判一下,或者給出一些更好的實現方案。
我們先來上一段代碼,就是常見的一種代碼。
Order getOrder(string orderNo) { order = repo.getOrder(orderNo); if(order.condition1) { ... } if(order.condition2) { ... } if(order.condition3) { ... } . . . }
上面是一段偽代碼,實現的就是一個根據訂單號,獲取訂單,然後根據訂單的一些條件進行一些處理。
order是獲取出來的訂單,condition1、condition2、condition3是一些條件。隨著業務的復雜,condition3後面還可能更多的condition,就需要添加更多的if,進行更多的判斷,然後這個方法越來越長,越來越難以讀懂,越來越難以維護,越來越。
我想是不是可以換個角度,不是訂單來判斷條件,然後執行一些代碼。而是訂單進入一個處理流程,然後處理流程中有很多的閘門,每個閘門代表一個特征條件處理器,然後由這個處理器來判斷流經自己的訂單是否符合條件,符合就處理,不符合就掠過。
這樣有幾個好處:
上面代碼中的獲取訂單方法,不會越來越長,這樣閱讀起來就很好理解,在後面進行維護的時候,就很容易來做了。
添加一個新的條件處理分支也很容易,只要把這種條件處理看做是一個閘門,在處理流水線中加入新閘門就可以了,其他的都不需要變化。
調整原來的條件處理,也只需要修改閘門內部的處理代碼即可,不用擔心是否影響其他處理分支。
分支獨立之後,還可以針對每個分支做單元測試。
其實擴展開來想,這個流程不僅可以處理訂單,任何針對一個對象進行流程化處理的場景,都可以套用上面的代碼結構,都可以得到上面的好處。
我畫了一個示意圖。
圖 1.1 對象處理流水線
放出一段示例代碼。
public interface IRepo { string getOrder(string orderNo); } public class Repo : IRepo { public string getOrder(string orderNo) { return string.Empty; } } public class Client { public void getOrder(string orderNo) { var order = new Repo().getOrder(orderNo); var pipeline = new Pipeline(); var handle1 = new condition1_Handle(); var handle2 = new condition2_Handle(); pipeline.add_order(order); pipeline.add_handle(handle1); pipeline.add_handle(handle2); pipeline.processOrder(); } } class Pipeline { private List<IHandle> _handles; private string _order; public Pipeline() { _handles = new List<IHandle>(); } internal void add_order(string order) { this._order = order; } internal void add_handle(IHandle handle1) { _handles.Add(handle1); } internal void processOrder() { foreach (var h in _handles) { h.process(_order); } } } public interface IHandle { void process(string order); } public class condition1_Handle : IHandle { public void process(string _order) { throw new NotImplementedException(); } } public class condition2_Handle : IHandle { public void process(string _order) { throw new NotImplementedException(); } }
查看本欄目
感覺有點像是策略模式,但是感覺又不太像。
上面的代碼還有優化的空間,大家有沒有更好的方案呢,歡迎大家一起討論!
稍加改進,引入泛型,就可以支持任意類型的對象處理。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleClient.Pipeline { public interface IRepo { Purchase getOrder(string orderNo); Product getProduct(int id); } public class Repo : IRepo { public Purchase getOrder(string orderNo) { return new Purchase(); } public Product getProduct(int id) { return new Product(); } } public class Client { public Purchase getOrder(string orderNo) { var order = new Repo().getOrder(orderNo); var pipeline = new Pipeline<Purchase>(); var handle1 = new condition1_orderHandle(); var handle2 = new condition2_orderHandle(); pipeline.add_order(order); pipeline.add_handle(handle1); pipeline.add_handle(handle2); pipeline.processOrder(); return order; } public Product getProduct(int id) { var product = new Repo().getProduct(id); var pipeline = new Pipeline<Product>(); var handle1 = new condition1_productHandle(); var handle2 = new condition2_productHandle(); pipeline.add_order(product); pipeline.add_handle(handle1); pipeline.add_handle(handle2); pipeline.processOrder(); return product; } } public class Pipeline<T> { private List<IHandle<T>> _handles; private T _order; public Pipeline() { _handles = new List<IHandle<T>>(); } public void add_order(T order) { this._order = order; } public void add_handle(IHandle<T> handle1) { _handles.Add(handle1); } public void processOrder() { foreach (var h in _handles) { h.process(_order); } } } public class Purchase { public bool IsPay { get; set; } } public class Product { public bool IsExpired { get; set; } } public interface IHandle<T> { void process(T order); } public class condition1_orderHandle : IHandle<Purchase> { public void process(Purchase order) { if (order.IsPay == false ) { Console.WriteLine("you don't pay money"); } } } public class condition2_orderHandle : IHandle<Purchase> { public void process(Purchase order) { } } public class condition1_productHandle : IHandle<Product> { public void process(Product product) { } } public class condition2_productHandle : IHandle<Product> { public void process(Product product) { } } }
本文出自 “突破中的IT結構師” 博客,請務必保留此出處http://virusswb.blog.51cto.com/115214/1081790