如何实现可互换/可切换的业务逻辑
本文关键字:业务 何实现 实现 可互换 | 更新日期: 2023-09-27 18:25:54
假设我有3项任务:注册、评估、注册。
我希望能够使我的应用程序在这个过程中有这3个可互换的位置。因此,对于一个设置,我可以进行注册->评估->注册。我可以将其他设置更改为"注册"->"报名"->"评估"。
此外,我还需要能够打开/关闭任务的一些功能(如注册)。
你们能告诉我从哪里开始吗?
我会建立一个责任链。来自GoF:
通过给多个对象处理请求的机会,避免将请求的发送方耦合到接收方。将接收对象链接起来,并沿着链接传递请求,直到对象处理为止。
下面是一个使用您给出的业务流程名称的简单示例:
// These all should be named something relevant to your domain
public interface IHandler
{
void Handle(string request);
}
public class Handler
{
protected IHandler successor;
protected Handler(IHandler successor)
{
this.successor = successor;
}
protected virtual void Successor(string request)
{
successor?.Handle(request);
}
}
public class Registration : Handler, IHandler
{
public Registration(IHandler successor)
: base(successor) { }
public void Handle(string request)
{
Console.WriteLine($"Registration handled request {request}");
base.Successor(request);
}
}
public class Enrollment : Handler, IHandler
{
public Enrollment(IHandler successor)
: base(successor) { }
public void Handle(string request)
{
Console.WriteLine($"Enrollment handled request {request}");
base.Successor(request);
}
}
public class Assessment : Handler, IHandler
{
public Assessment(IHandler successor)
: base(successor) { }
public void Handle(string request)
{
if (request.Equals("Bob", StringComparison.InvariantCulture))
{
Console.WriteLine("Bob failed assessment.");
return;
}
Console.WriteLine($"Assessment handled request {request}");
base.Successor(request);
}
}
和示例用法:
// Consumers of this don't need to know anything more than it's an IHandler service
// Consumers of this don't need to know anything more than it's an IHandler service
IHandler noregistrationHandlers = new Assessment(new Enrollment(null));
// or Autofac
// builder.Register(c => new Assessment(c.Resolve<Enrollment>(null))).Named("NoRegistration");
// or your favorite IoC container
noregistrationHandlers.Handle("Smith");
IHandler registrationHandlers = new Registration(new Assessment(new Enrollment(null)));
// builder.Register(c => new Registration(c.Resolve<Assessment>(c.Resolve<Enrollment>(null)))).Named("Registration");
registrationHandlers.Handle("Bob");
这方面的要点是:消费代码(使用示例)除了向处理程序发送请求的格式之外,不需要知道任何东西。在示例中调用构造函数只是为了示例的方便。你可以很好地拥有一个MVC控制器,它依赖于IHandler
,但对它一无所知
public class UserController
{
private readonly IHandler handler;
public UserController(IHandler handler)
{
if (handler == null) throw new NullReferenceException(nameof(handler));
this.handler = handler;
}
// ...
public ActionResult Save(string id)
{
handler(id);
}
}