我有一个场景,我将数据'request'对象传递给服务,并且服务本身必须根据请求中的数据创建许多不同的'处理器'。
每个处理器本身可以是多种不同类型中的一种。例如,粗略的丑陋实现可能看起来像:
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;
}
我正在寻找一种可扩展的模式,并隐藏了决定服务需要创建的处理器类型的讨厌逻辑,因此它比上面的丑陋代码更清晰,更易于维护。
我了解工厂方法,但仅靠这些方法是不够的。
建议表示赞赏。
答案 0 :(得分:2)
一种想到的模式是责任链(可能不是创作模式)
首先,您需要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);
}
}
}
}
希望这会有所帮助。欢呼声。
答案 1 :(得分:1)
工厂可能是正确的方法,但你需要更多的东西,即配置。
例如,您可能需要一个类似于
的配置文件<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);
答案 2 :(得分:1)
您要做的是创建工厂,主要问题是您希望如何配置它。我喜欢遵循一种方法,选择应该创建哪种方法属于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容器。