2009-10-19 3 views
1

Я борюсь с небольшой проблемой в отношении того, как я собираюсь реорганизовать это на приличный шаблон.Как реорганизовать это?

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

В чем проблема? возможно, я отстаю от времени, но мне рефакторинг не кажется необходимым для такого упрощенного примера. –

+0

Дело в том, что мне нужно будет добавить еще несколько документов в ближайшее время, и мне не нравится идея добавлять этот метод каждый раз. – Jimmeh

+0

Если вы собираетесь добавлять дополнительные документы, создайте базовый класс для предоставления этих методов. Я думаю, что, вероятно, я не понимаю проблему. я буду следить за чем-то. –

ответ

5

Лично я бы рассмотрел либо заводской шаблон, используя заводские методы, либо шаблон строителя.

Хорошее использование шаблона фабрики можно увидеть в решении Enterprise Library, например: Database.CreateDatabase();
Я бы сказал, что это было бы самым прямым для интеграции.

Если вы выбрали шаблон Builder с требованием создания более сложных объектов, то вы можете выделить создание сложных объектов в серию команд сборки, например: vehicleBuilder.BuildFrame(); vehicleBuilder.BuildEngine(); vehicleBuilder.BuildWheels(); vehicleBuilder.BuildDoors();

Затем в рамках этих методов, с учетом выбранной вами реализации, вы можете добавить свою сложность, но сделать вызовы и конструкцию метода достаточно простыми.

Если вы не столкнулись с этим, http://www.dofactory.com - хорошее место для работы.

+0

I'vev использовал этот подход, поэтому я выберу это как правильный ответ. Спасибо. – Jimmeh

0

что по этому поводу:

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

Из верхней части моей головы, поэтому может содержать вопиющую ошибку ;-)

+0

Это нормально, но накладывает на клиента обязательство знать, какого рода работник они делают. Вполне вероятно, что в конечном итоге мы получим какой-то оператор switch в клиенте. – djna

+0

В классах «Контракт» и «Назначение» используются только входные параметры для их создания, они не содержат их как часть состояния. Должно быть, это было более ясно. – Jimmeh

1

Я вижу два аспекта:

  1. Что мне нужно сделать, чтобы добавить новый класс IWorkerDocument? Добавление новых методов кажется тяжеловесным.
  2. Какой код нужен вызывающему для создания IWorkerDocument? В настоящее время ответственность за вызов правильного метода лежит на вызывающем абоненте, поэтому вполне вероятно, что вызывающий абонент также должен меняться каждый раз, когда есть новый разработчик IWorkerDocument.

Размер рефакторинга зависит от ответа на вопрос 2. Иногда вызывающий абонент просто должен знать, что они делают, и в этом случае код, который у вас есть, - это почти все, что вы можете сделать. В других случаях у вас есть материал «WorkerDefinition», возможно, в виде набора свойств или имя, которое можно найти в реестре. В этом случае, вызывающему абоненту требуется априота

makeMeAWorker(WorkerDefinition def) 

на заводе. Теперь звонящий понятия не имеет, о чем он просит, передает все это на заводе. Таким образом, мир клиента не должен меняться при добавлении новых типов Рабочих.

Фабрика может быть расширена с помощью какой-либо формы схемы регистрации или схемы динамической конфигурации.Мы можем вводить новые типы на завод многими различными механизмами.

1

Я думаю, что это зависит от других обязанностей класса, который содержит эти методы. Шаблоны проектирования - это структурные конструкции. Здесь мы делаем вывод, что существует

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

    public IWorkerDocument AttemptAssignmentRetrieval() 
    { 
    } 
} 

код Клиентский класс уже решить, стоит ли называть AttemptContractRetrieval(), или AttemptAssignmentRetrieval, поэтому, возможно, полиморфизм в порядке.

class ContractRetriever 
{ 
    public IWorkerDocument AttemptRetrieval() 
    { 
    } 
} 

class AssignmentRetriever 
{ 
    public IWorkerDocument AttemptRetrieval() 
    { 
    } 
} 

Вы можете сделать абстрактный класс ретривера и иметь их в качестве потомков. Это заставит производные классы иметь метод AttemptRetrieval().

Если вы выполняете аналогичные действия по извлеченным документам, вы можете рассмотреть наличие классов контрактов и присвоений вместо ContractRetriever и AssignmentRetriever. Затем вы можете установить общие действия в своем родителе.

Короче говоря, здесь много ответа лежит в неустановленном контексте проблемы.

+0

ОК. Первоначальный вопрос был сформулирован после этого ответа. –

+0

Да, извините. Первоначально я не хотел слишком много вкладывать, чтобы я мог держать его как можно более кратким, но стало ясно, что нужно немного контекста. J. – Jimmeh

+0

Я думаю, что у меня была бы библиотека как создатель экземпляров экземпляров LibraryDocument, которые были бы суперклассом Contract, Assignment и т. Д.Библиотека отвечает за отслеживание файлов пользователей и файлов (хотя позже они могут оказаться отчетливыми.), А подклассы LibraryDocument отвечают за создание и работу с отдельным документом IWorkerDocument. Заводские образцы, упомянутые в других сообщениях, заслуживают проверки. –

0

Вы ищете шаблон абстрактного завода? Объявленная цель в «Design Patterns» - «Предоставить интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов».

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

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

Это немного грязный, так есть ли какие-либо предложения, чтобы очистить фактический фабричный метод вверх?

Смежные вопросы