如何实现可互换/可切换的业务逻辑

本文关键字:业务 何实现 实现 可互换 | 更新日期: 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);
    }
}