本文用到的編程語言為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