我目前正考虑采用何种模式解决以下问题。
我有一个名为IdentificationRequest
的实体。该实体用于通过某些标准识别Person
。
public class IdentificationRequest
{
public IdentificationCriteria Criteria;
public Person IdentifiedPerson;
protected internal virtual void RedirectToManualIdentification()
{
ChangeState(IdentificationRequestState.ManualIdentificationRequested);
}
public virtual void StartManualIdentification()
{
ChangeState(IdentificationRequestState.ManualIdentificationInProgress);
}
public virtual void AssignIdentifiedPerson(Person person)
{
identifiedPerson = person;
ChangeState(IdentificationRequestState.IdentificationFinished);
}
}
public class IdentificationCriteria
{
public string Name;
}
这是一个简化的例子。实际上,IdentificationRequest
包含更多信息,以及IdentificationCriteria
。
基本上,客户端使用IdentificationRequest
创建IdentificationCriteria
,然后需要识别正确的Person
。为此,需要将标准传递给持久层,以检查数据库中是否有符合条件的人员。如果找不到人,则需要进行人工干预,以便为请求分配正确的Person
。
对于识别过程,我目前正在使用服务。像:
public class IdentificationService : IIdentificationService
{
private readonly IPersonRepository personRepository ;
private readonly IIdentificationRequestRepository identificationRequestRepository;
public IdentificationService(IPersonRepository personRepository )
{
this.personRepository = personRepository ;
}
public bool IdentifyPerson(IdentificationRequest identificationRequest)
{
var matches = personRepository.FindByIdentificationCriteria(identificationRequest.Criteria);
// some additional post analysis of the matches returned from the persistence layer
var criteriaAnalyzer = new IdentificationCriteriaAnalyzer(identificationRequest.Criteria);
var uniqueMatch = criteriaAnalyzer.TryIdentify(matches);
if(uniqueMatch != null)
{
identificationRequest.AssignIdentifiedPerson(uniqueMatch);
return true;
}
else
{
identificationRequest.RedirectToManualIdentification();
return false;
}
}
}
此服务是域程序集的一部分。现在我的问题是,如果这是执行识别的正确模式?或者我会使用工厂来创建识别请求,然后直接尝试识别它,例如:
public class IdentificationRequestFactory
{
private readonly IPersonRepository personRepository;
public IdentificationRequestFactory(IPersonRepository personRepository)
{
this.personRepository = personRepository;
}
public IdentificationRequest Create(IdentificationCriteria identificationCriteria)
{
var request = new IdentificationRequest(identificationCriteria);
var matches = personRepository.FindByIdentificationCriteria(identificationRequest.Criteria);
var criteriaAnalyzer = new IdentificationCriteriaAnalyzer(identificationRequest.Criteria);
var uniqueMatch = criteriaAnalyzer.TryIdentify(matches);
if(uniqueMatch != null)
{
identificationRequest.AssignIdentifiedPerson(uniqueMatch);
}
else
{
identificationRequest.RedirectToManualIdentification();
}
return request;
}
}
这样,IdentificationRequest
只能由工厂构建,确保已经完成识别过程并且请求处于有效状态。
或者你会让IdentificationRequest
通过像下面这样的方法注入来识别自己:
public class IdentificationRequest
{
public IdentificationCriteria Criteria;
public Person IdentifiedPerson;
public void Identify(IPersonRepository personRepository)
{
// identification logic here
}
}
此示例将识别过程直接耦合到请求。
这种情况的常见模式是什么?反正有共同的模式吗?有什么优点和缺点?
提前谢谢!更新
也许我没有正确理解命令模式,但在这种情况下我能得到什么好处?以下实现是否正确?
public class IdentificationCommandFactory
{
private readonly IPersonRepository personRepository;
public IdentificationCommandFactory(IPersonRepository personRepository)
{
this.personRepository = personRepository;
}
public IIdentificationCommand Create(IdentificationRequest identificationRequest)
{
var matches = personRepository.FindByIdentificationCriteria(identificationRequest);
var criteriaAnalyzer = new IdentificationCriteriaAnalyzer(identificationRequest);
var uniqueMatch = criteriaAnalyzer.TryIdentify(matches);
if(uniqueMatch != null)
{
return new AssignIdentifiedPersonCommand(identificationRequest, uniqueMatch);
}
else
{
return new RedirectToManualIdentificationCommand(identificationRequest);
}
}
}
public interface IIdentificationCommand
{
void Execute();
}
public class RedirectToManualIdentificationCommand : IIdentificationCommand
{
private readonly IdentificationRequest identificationRequest;
public RedirectToManualIdentificationCommand(IdentificationRequest identificationRequest)
{
this.identificationRequest = identificationRequest;
}
public void Execute()
{
identificationRequest.RedirectToManualIdentification();
}
}
public class AssignIdentifiedPersonCommand : IIdentificationCommand
{
private readonly IdentificationRequest identificationRequest;
private readonly Person personIdentified;
public AssignIdentifiedPersonCommand(IdentificationRequest identificationRequest, Person personIdentified)
{
this.identificationRequest = identificationRequest;
this.personIdentified = personIdentified;
}
public void Execute()
{
identificationRequest.AssignIdentifiedPerson(personIdentified);
}
}
来电者:
var identificationCommandFactory = new IdentificationCommandFactory(personRepository);
var command = identificationCommandFactory.Create(request);
command.Execute();
答案 0 :(得分:5)
开发的主要目标应该是使用最简单,最干净的代码来满足要求。 (http://msdn.microsoft.com/en-us/magazine/cc163962.aspx)
话虽如此,除非您有特定理由使用其中一种模式,否则请立即停止。如果没有具体的理由去做这项工作,你只需编写更多的代码,希望它有一天会有用。只要写出有效的方法。如果需要,稍后重构它。
如果需要,继续沿着保持简单的道路前进。选择一个模式,库或其他工具,使您可以编写干净,简单,可读的代码来完成工作。
答案 1 :(得分:0)
您的IdentificationCriteria和IdentificationCriteriaAnalyzer类型在我看来很像Specifications,所以我会看看在这个方向重构它们是否有意义。
在我看来,IdentificationRequest类打破了Single Responsibility Principle - 为什么它有一个Person字段/属性?
API也可以从更好的Command-Query Separation中受益。
所以我认为更好的模型是定义一个接受IdentificationCriteria并返回某种Command的接口。这样的界面基本上是抽象工厂。
public interface IIdentificationCommandFactory
{
IIdentificationCommand Create(IdentificationCriteria spec);
}
当您实现它时,您可以在您的repostiry中查找匹配项,并根据该查询的结果和您的其他规范(例如IdentificationCriteriaAnalyzer),您可以返回正确的IIdentificationCommand实现。
然后调用者会要求返回的命令执行。
答案 2 :(得分:0)
在我看来,你应该使用命令模式:
- http://www.dofactory.com/Patterns/PatternCommand.aspx
- http://c2.com/cgi/wiki?CommandPattern
- http://en.wikipedia.org/wiki/Command_pattern
此外,您的IdentificationRequest不像entity class,但我会将您的Person类描述为实体。
通常命令模式中的Invoker向接收者发送响应,指示成功或失败,并且在成功的情况下,响应对象可以包含已识别的角色。