代码之家  ›  专栏  ›  技术社区  ›  Jimmeh

如何重构这个?

  •  1
  • Jimmeh  · 技术社区  · 15 年前

    关于如何将其重构为一个合适的模式,我正在努力解决一个小问题。

    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 )以一种体面的形式。

    任何帮助都将不胜感激。

    当做, 吉姆。

    6 回复  |  直到 15 年前
        1
  •  5
  •   Alex H    15 年前

    个人而言,我会考虑使用工厂方法的工厂模式或构建器模式。

    在企业库解决方案中可以看到工厂模式的良好使用,例如: database.createdatabase();
    我认为这将是最直接的整合。

    如果选择了构建器模式,并要求创建更复杂的对象,则可以将复杂对象的创建分离为一系列构建命令,例如: vehicleBuilder.buildFrame(); vehicleBuilder.buildEngine(); vehicleBuilder.buildWheels(); vehiclebuilder.builddoors();

    然后,在这些方法中,考虑到您选择的实现,您可以增加复杂性,但使方法调用和构造非常直接。

    如果你没有遇到它, http://www.dofactory.com 是个好去处。

        2
  •  1
  •   djna    15 年前

    我可以看到两个方面:

    1. 添加新的iWorkerDocument类需要做什么?添加新方法似乎很重要。
    2. 调用方需要什么代码才能创建iWorkerDocument?现在,调用正确方法的责任由调用方承担,因此,调用方很可能也需要在每次有新的iWorkerDocument实现时进行更改。

    可能的重构程度很大程度上取决于对2的回答。有时,调用者只需要知道他们在做什么,在这种情况下,您所拥有的代码几乎是您所能做的。在其他情况下,您有一些“WorkerDefinition”的东西,可能是以一组属性的形式,或者可以在注册表中查找的名称。在这种情况下,调用方需要表单的API

     makeMeAWorker(WorkerDefinition def)
    

    在工厂里。现在打电话的人不知道他要什么,就把整个事情委托给工厂。因此,当您添加新的工人类型时,客户机的世界不需要改变。

    工厂可以通过某种形式的注册方案或动态配置方案进行扩展。我们可以通过许多不同的机制向工厂注入新的类型。

        3
  •  1
  •   Ewan Todd    15 年前

    我认为这取决于类还有哪些包含这些方法的职责。设计模式是结构构造。在这里我们推断有一个班级

    class Retriever
    {
      ...
      public IWorkerDocument AttemptContractRetrieval()
      {
      }
    
      public IWorkerDocument AttemptAssignmentRetrieval()
      {
      }
    }
    

    客户机代码已经决定是调用attemptContractRetrieval()还是attemptAssignmentRetrieval,因此多态性可能是正确的。

    class ContractRetriever
    {
       public IWorkerDocument AttemptRetrieval()
       {
       }
    }
    
    class AssignmentRetriever
    {
       public IWorkerDocument AttemptRetrieval()
       {
       }
    }
    

    您可以创建一个抽象的检索器类,并将这些类作为它的后代。这将强制派生类具有attemptRetrieval()方法。

    如果对检索到的文档执行类似的操作,则可以考虑使用Contract和Assignment类,而不是ContractRetriever和AssignmentRetriever。然后您可以在他们的父级中放置常见操作。

    简而言之,这里的很多答案都是在问题的未说明的背景下得出的。

        4
  •  1
  •   Jimmeh    15 年前

    对于感兴趣的人来说,我已经开始采用工厂方法了。

    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");
     }
    

    有点乱,有人建议把工厂的实际方法清理一下吗?

        5
  •  0
  •   Dabblernl    15 年前

    这个怎么样:

      public IWorkerDocument AttemptRetrieval<T>() where T:new, IWorkerDocument
         {
             return new T {FileSystem=fileSystem,User=user}
         }
    

    在我的头上,所以可能包含一个明显的错误;-)

        6
  •  0
  •   Robert Gowland    15 年前

    你在找抽象的工厂模式吗?“设计模式”中声明的意图是“提供一个接口,用于创建相关或依赖对象的族,而不指定它们的具体类。”

    http://en.wikipedia.org/wiki/Abstract_factory