Требуется заводская модель - PullRequest
1 голос
/ 30 декабря 2008

Я работаю над тем, чтобы обернуть голову вокруг фабричного шаблона, используя его в простом проекте хранения данных в свободное время. Идея состоит в том, чтобы взять простые данные и сохранить их в базе данных, используя простой шаблон фабрики в VB.NET. Я думаю, что у меня есть базовое понимание самого шаблона, однако, я борюсь с тем, как аккуратно вписать фабричные классы в архитектуру. У меня есть стандартная 3-уровневая архитектура для этого проекта, которая выглядит примерно так:

Презентация

 -Presentation.Common
 -Presentation.DataStorageWebAppName

Бизнес

 -BusinessLayer.Common
 -BusinessLayer.DataStorageAppName

Данные

 -DataLayer.Common
 -DataLayer.DataStorageAppName

Общее

 -Common
 -Common.DataStorageAppName

Интерфейсы

 -Interfaces.Common
 -Interfaces.DataStorageAppName

Чтобы выделить конкретный сценарий, в котором у меня возникают проблемы при разработке приложения, приведу пример. Допустим, на бизнес-уровне я создаю класс в DLL-библиотеке BusinessLayer.DataStorageAppName с именем Foo. Он имеет интерфейс IFoo, который находится в DLL-библиотеке Interfaces.DataStorageAppName. Чтобы создать экземпляр класса Foo через его интерфейс IFoo, используя простой шаблон фабрики, прямо сейчас я создаю класс Factory в BusinessLayer.DataStorageAppName и пишу метод shared / static, чтобы предоставить мне экземпляр через интерфейс IFoo. Позже, насколько я понимаю, я мог решить поменять объект, возвращаемый классом Factory, без необходимости делать что-либо еще (теоретически).

Чтобы перейти к сути, это работает, но то, что кажется странным, так это то, что я теперь вынужден создать несколько классов Factory: по одному на каждую DLL, чтобы я мог избежать циклических ссылок. Есть ли более чистый способ реализовать эти фабричные классы, не прибегая к использованию сторонних решений, таких как замок Виндзор и т. Д. И т. Д. Кажется, здесь я упускаю фундаментальную концепцию. Похоже, что в архитектуре, которая отвечает за раздачу экземпляров объектов, должно быть возможно иметь один «репозиторий».

Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 30 декабря 2008

Существует ли причина, по которой ваша реализация IFoo и метода фабрики, который возвращает его, не может находиться в отдельной сборке от BusinessLayer (и, таким образом, вы можете ссылаться на эту новую сборку из всех клиентских сборок)? Если есть причина, возможно ли, что IFoo должен быть определен также в BusinessLayer (и, следовательно, не требует ссылок на сборку интерфейсов)?

Если ваш интерфейс действительно должен быть доступен не из бизнес-уровня, а реализация действительно зависит от бизнес-уровня, вам нужно взглянуть на нечто большее, чем просто фабричный метод. Вы можете использовать некоторые принципы Инверсии Контроля / Внедрения Зависимостей, чтобы лучше разделить проблемы.

[Изменить в ответ на последующий ответ О.П.] Фабричный метод, IMO, не достаточен, чтобы считаться подходом IoC. Лучше всего инкапсулировать конструкцию конкретной реализации, для повторного использования в нескольких местах или просто для подметания под коврик . Чего мне не хватает, так это разрыва зависимостей: поскольку ваш фабричный метод находится в той же сборке, из которой он вызывается, для изменения возвращаемого конкретного типа вам потребуется перекомпилировать. Рассмотрим разницу между следующими двумя:

public class FooConsumer1
{
    public void DoStuff()
    {
        IFoo myFoo = new Foo();
        myFoo.Bar();
    }
}

и

public class FooConsumer2
{
    public void DoStuff()
    {
        IFoo myFoo = FooFactory.getFoo();
        myFoo.Bar();
    }
}

public class FooFactory
{
    public static IFoo GetFoo()
    {
        return new Foo();
    }
}

Преимущество второго состоит в том, что если вы создаете IFoo более чем в одном месте, у вас есть только одно место, чтобы изменить его, когда вы создаете класс SuperFoo для замены Foo. Кроме того, есть только одно место для размещения логики, если она каким-то образом будет динамически выбирать между двумя реализациями. Другое преимущество состоит в том, что если конструктор сложен / безобразен или требует некоторого дополнительного кода для поиска параметров конфигурации или чего-то подобного, то он скрывает все это от метода, который его использует.

Однако, ни один из них на самом деле (по крайней мере, на мой взгляд) не помогает вам сломать зависимости между этим методом и конкретной реализацией, которую он использует.

1 голос
/ 30 декабря 2008

Я выбрал более простой подход. Я определил класс Entity, и у меня есть фабрика, которая создает список объектов (List ). Я сообщаю фабрике, какие типы я хочу получить, она предполагает, что тип является таблицей, свойства - столбцами, генерирует sql, получает данные, заполняет список новых экземпляров типа.

Фабрика также может получить объект Entity и использовать отражение для обновления своих значений в базе данных.

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

0 голосов
/ 31 декабря 2008

Необязательно иметь несколько фабричных классов, если они решают разные задачи. Я бы посоветовал не использовать статические фабричные методы, а создавать экземпляры используемых вами фабрик. Тогда сами фабрики могут реализовать интерфейсы, и, возможно, некоторые из них исчезнут.

...