什么样的创造性设计模式适合这些要求

本文关键字:创造性 设计模式 什么样 | 更新日期: 2023-09-27 18:04:45

我有一个场景,我将一个数据"请求"对象传递给一个服务,服务本身必须根据请求中的数据创建许多不同的"处理器"。

每个处理器本身可以是许多不同类型中的一种。例如,一个粗糙而丑陋的实现可能是这样的:

public Collection<IProcessor> UglyCreationalMethod(Request request)
{
    var processors = new Collection<IProcessor>();
    if(request.Type == RequestType.SomeVal)
    {
        if(request.Id > 1000)
        {
            processors.Add(new ProcessLargeRequest(request));
        }
        else
        {
            processors.Add(new ProcessSmallRequest(request));
        }
    }
    else (request.Type == RequestType.SomeOtherVal)
    {
        if(request.Source == RequestSource.User)
        {
            processors.Add(new ProcessUserRequest(request));
        }
        else
        {
            processors.Add(new ProcessCorpRequest(request));
        }
    }
    if(request.SomeProp == "blah")
        processors.Add(new ProcessBlahRequest(request));
    // ... etc ad infinitum :)
    return processors;
}

我正在寻找一种可扩展的模式,并且隐藏了决定服务需要创建的处理器类型的讨厌的逻辑,因此它比上面的丑陋代码更干净,更易于维护。

我知道工厂方法,但只有这些是不够的。

建议感激。

什么样的创造性设计模式适合这些要求

我想到的一个模式是责任链(也许不是创建模式)

首先,需要RequestHandlers

public interface IRequestHandler
    {
        bool CanHandle(Request req);
        void Handle(Request req);
    }
    public class LargeRequestHandler : IRequestHandler
    {
        public bool CanHandle(Request req)
        {
            return (req.Type == RequestType.SomeVal && req.id > 1000);
        }
        public void Handle(Request req)
        {
            processors.Add(new ProcessLargeRequest(request));
        }
    }
    public class SmallRequestHandler : IRequestHandler
    {
        public bool CanHandle(Request req)
        {
            return (req.Type == RequestType.SomeVal && req.id < 1000);
        }
        public void Handle(Request req)
        {
            processors.Add(new SmallLargeRequest(request));
        }
    }

…同样地,根据需要为更多的处理程序添加类。

然后创建这些处理程序的链,如

public class RequestChain
    {
        IRequestHandler[] handlers;
        public RequestChain()
        {
            handlers = new[] { new LargeRequestHandler(), new SmallRequestHandler() };
        }
        public void ProcessRequest(Request req)
        {
            foreach (var handler in handlers)
            {
                if (handler.CanHandle(req))
                {
                    handler.Handle(req);
                }
            }
        }
    }

希望这对你有帮助。欢呼。

你要做的是创建一个工厂,主要的问题是你想如何配置它。我喜欢遵循这样一种方法,即选择应该在Factory的职责中创建哪个方法,而不是在正在创建的类中—它会带来更好的可配置性,并且更容易管理。

我将创建如下内容:

    public struct ProcessorCreationSettings
    {
        public Predicate<Request> Predicate;
        public Func<Request, IProcessor> Creator;
    }
    public class ProcessorFactory
    {
        protected static List<ProcessorCreationSettings> settings = new List<ProcessorCreationSettings>();
        static ProcessorFactory()
        {
            settings.Add(new ProcessorCreationSettings
            {
                Predicate = r => r.Type == RequestType.SomeOther && r.Id > 1000,
                Creator = r => new ProcessLargeRequest(r)
            });
            settings.Add(new ProcessorCreationSettings
            {
                Predicate = r => r.Type == RequestType.SomeOther && r.Id <= 1000,
                Creator = r => new ProcessSmallRequest(r)
            });
        }
        public List<IProcessor> Create(Request request)
        {
            return settings
                .Where(s => s.Predicate(request))
                .Select(s => s.Creator(request))
                .ToList();
        }
    }

配置部分是由静态列表完成的,但是如果它有这样的特性,您也可以使用IoC容器。

工厂可能是正确的方法,但是您需要更多的支持,即配置。

例如,您可能希望配置文件看起来像

<processor type="typename">
  <rules>
    <rule type="requestIdThresholdRule">
      <configuration evaluationType="ExceedsThreshold" threshold="1000"/>
    </rule>
  </rules>
</processor>
<processor type="othertypename">
  <rules>
    <rule type="yadda">
       <configuration evaluationType="DoesNotMeetThreshold" threshold="1000"/>
    </rule>
  </rules>

这允许您在基于上下文的运行时计算来定义创建哪些类型时具有很大的灵活性。工厂方法本身并没有大量的代码,而是在一些主要由配置值驱动的规则中。更少的代码,更灵活。

那么你就把它命名为:

 List<ISomething> items = ISomethingFactory.CreateISomethingsForContext(context);