我有一个下单的方法,
public async Task<bool> Order(Request request)
{
// Each step does different things.
await Step1(request);
await Step2(request);
await Step3(request);
await Step4(request);
...
await StepN(request);
}
public async Task<bool> Step1(Request request)
{
var amount1 = await changeSomething1(request);
await Pay1(amount1);
}
public async Task<bool> Step2(Request request)
{
var amount2 = await changeSomething2(request);
await Pay2(amount2);
}
public async Task<bool> StepX(Request request)
{
var amountX = await changeSomethingX(request);
await PayX(amountX);
}
现在我需要在没有调用任何PayX(amount)
的情况下预览订单。我不想添加一个boolen参数来跳过它,就像下面的代码一样,它看起来很难看。
public async Task<bool> Order(Request request, bool preview = false)
{
await Step1(request, preview);
await Step2(request, preview);
await Step3(request, preview);
await Step4(request, preview);
....
await StepN(request, preview);
}
public async Task<bool> StepX(Request request, bool preview = false)
{
var amountX = await changeSomethingX(request);
if(!preview) await PayX(amountX);
}
这里可以应用什么模式?非常感谢。
在我看来,您需要一些类似中间件的模式(例如Asp.Net中的中间件(。这是我的建议:
首先创建一个OrderMiddleware类,它封装了您的两个方法,Step和Pay。在这种情况下,我们将步骤和付款作为委托给构造函数,以实现最大的灵活性
public delegate Task<int> StepDelegate(Request request);
public delegate Task PayDelegate(int amount);
public class OrderMiddleware
{
// Private fields
private readonly StepDelegate _step;
private readonly PayDelegate _pay;
// Initialization
public OrderMiddleware(StepDelegate step, PayDelegate pay)
{
_step = step;
_pay = pay;
}
// Public
public async Task Order(Request request, bool preview)
{
var amount = await _step.Invoke(request);
if (!preview)
await _pay.Invoke(amount);
}
}
然后,您需要一个类来处理一个OrderMiddlewares列表,该列表表示您的完整管道。
public class OrderPipeline
{
// Private fields
private readonly List<OrderMiddleware> _orderMiddlewares;
// Initialization
public OrderPipeline()
{
_orderMiddlewares = new()
{
new(Step1, Pay1),
new(Step2, Pay2)
};
}
// Order Handling
public async Task Order(Request request, bool preview = false)
{
foreach(var middleware in _orderMiddlewares)
await middleware.Order(request, preview);
}
// Middlewares
public async Task Step1(Request request)
{
var amount1 = await changeSomething1(request);
await Pay1(amount1);
}
public async Task Step2(Request request)
{
var amount2 = await changeSomething2(request);
await Pay2(amount2);
}
}
通过这种方式,order方法可以处理中间件列表。只有几个注意事项:
如果您需要向每个中间件传递其他参数,请考虑创建一个OrderConfiguration类来封装所有这些数据,然后传递它。通过这种方式,签名保持干净,您不需要进行任何重构
也许您想将中间件注册逻辑与OrderPipeline类分离,以避免违反开放-关闭原则:
public class OrderPipeline
{
// Private fields
private readonly List<OrderMiddleware> _orderMiddlewares = new();
// Order Handling
public async Task Order(Request request, bool preview = false)
{
foreach(var middleware in _orderMiddlewares)
await middleware.Order(request, preview);
}
public void AddMiddleware(OrderMiddleware orderMiddleware)
{
_orderMiddlewares.Add(orderMiddleware);
}
}