关于如何将其重构为一个体面的模式,我正在努力解决一个小问题。
public class DocumentLibrary
{
private IFileSystem fileSystem;
private IDocumentLibraryUser user;
public DocumentLibrary(IDocumentLibraryUser user) : this(user, FileSystemFrom(user)) { }
public DocumentLibrary(IDocumentLibraryUser user, IFileSystem fileSystem)
{
this.user = user;
this.fileSystem = fileSystem;
}
public void Create(IWorkerDocument document)
{
document.SaveTo(fileSystem);
}
public IWorkerDocument AttemptContractRetrieval()
{
return new Contract(fileSystem, user);
}
public IWorkerDocument AttemptAssignmentRetrieval()
{
return new Assignment(fileSystem, user);
}
private static IFileSystem FileSystemFrom(IDocumentLibraryUser user)
{
var userLibraryDirectory = new DirectoryInfo("/DocLib/" + EnvironmentName() + "/" + user.Id);
return new FileSystem(userLibraryDirectory);
}
private static string EnvironmentName()
{
using (var edmxContext = new Entities())
{
return (from setting in edmxContext.EnvironmentSettings
where setting.Name == "EnvironmentName"
select setting.Value).First();
}
}
}
我有两种类型的工作文档,但我似乎无法轻易地将上述两种方法(AttemptContractRetrieval
和AttemptAssignmentRetrieval
)重构为一种体面的形式。
非常感谢任何帮助。
此致 吉姆。
答案 0 :(得分:5)
在个人情况下,我会考虑使用工厂方法的工厂模式或构建器模式。
在Enterprise Library解决方案中可以看到工厂模式的良好使用,例如:
Database.CreateDatabase();
我想说这将是最直接的整合。
如果您选择了构建器模式,并且需要创建更复杂的对象,那么您可以将复杂对象的创建分离为一系列构建命令,例如: vehicleBuilder.BuildFrame(); vehicleBuilder.BuildEngine(); vehicleBuilder.BuildWheels(); vehicleBuilder.BuildDoors();
然后在这些方法中,根据您选择的实现,您可以添加您的复杂性,但是方法调用和构造非常直接。
如果您没有遇到过,http://www.dofactory.com是一个不错的去处。
答案 1 :(得分:1)
我可以看到两个方面:
可能的重构程度在很大程度上取决于2的答案。有时调用者只需知道他们正在制作什么,在这种情况下,你拥有的代码几乎就是你所能做的。在其他情况下,您有一些“WorkerDefinition”内容,可能是一组Properties的形式,或者可以在注册表中查找的名称。在这种情况下,调用者想要一个
形式的api makeMeAWorker(WorkerDefinition def)
在工厂。现在,来电者不知道他要求的是什么,将整个事情委托给工厂。因此,当您添加新的Worker类型时,客户端的世界不需要更改。
可以通过某种形式的注册方案或动态配置方案使工厂可扩展。我们可以通过许多不同的机制将新类型注入工厂。
答案 2 :(得分:1)
我认为这取决于该类包含这些方法的其他职责。设计模式是结构构造。在这里我们推断出有一个类
class Retriever
{
...
public IWorkerDocument AttemptContractRetrieval()
{
}
public IWorkerDocument AttemptAssignmentRetrieval()
{
}
}
客户端代码已经决定是否调用AttemptContractRetrieval()或AttemptAssignmentRetrieval,因此可能是多态性。
class ContractRetriever
{
public IWorkerDocument AttemptRetrieval()
{
}
}
class AssignmentRetriever
{
public IWorkerDocument AttemptRetrieval()
{
}
}
您可以创建一个抽象的Retriever类,并将其作为后代。这将强制派生类具有AttemptRetrieval()方法。
如果对检索到的文档执行类似操作,则可以考虑使用Contract和Assignment类而不是ContractRetriever和AssignmentRetriever。然后你可以将共同的行动放在他们的父母身上。
简而言之,这里的答案很多都在于问题的未说明背景。
答案 3 :(得分:1)
对于感兴趣的人,我去了一个工厂方法。
public IWorkerDocument AttemptRetrieval<T>() where T : IWorkerDocument
{
return WorkerDocument.Create<T>(fileSystem, user);
}
来电
public static IWorkerDocument Create<T>(IFileSystem fileSystem, IDocumentLibraryUser user) where T : IWorkerDocument
{
var documentType = typeof(T);
if (documentType == typeof(Contract))
return new Contract(fileSystem, user);
if (documentType == typeof(Assignment))
return new Assignment(fileSystem, user);
throw new Exception("Invalid Document Type");
}
这有点乱,所以有人有任何建议来清理实际的工厂方法吗?
答案 4 :(得分:0)
怎么样:
public IWorkerDocument AttemptRetrieval<T>() where T:new, IWorkerDocument
{
return new T {FileSystem=fileSystem,User=user}
}
在我的头顶,所以可能包含明显的错误; - )
答案 5 :(得分:0)
您在寻找抽象工厂模式吗? “设计模式”中声明的意图是“提供用于创建相关或依赖对象族的接口,而无需指定其具体类。”