Я смотрю на этот пример, чтобы понять использование заводского шаблона.
Я действительно аматор в этой области, поэтому извините мой глупый вопрос.
Моя проблема заключается в том, что я не вижу использования фабричного шаблона, который возвращает нам интерфейс, который мы можем вводить непосредственно, когда нам нужно его использовать.
В приведенном выше примере я бы сделал следующее:
public class Program
{
// register the interfaces with DI container in a separate config class (Unity in this case)
private readonly IShippingStrategy _shippingStrategy;
public Program(IShippingStrategy shippingStrategy)
{
_shippingStrategy= shippingStrategy;
}
public int DoTheWork(Order order)
{
// assign properties just as an example
order.ShippingMethod = "Fedex";
order.OrderTotal = 90;
order.OrderWeight = 12;
order.OrderZipCode = 98109;
int shippingCost = _shippingStrategy.CalculateShippingCost(order);
return shippingCost;
}
}
Вместо того, чтобы вводить завод:
public class Program
{
// register the interfaces with DI container in a separate config class (Unity in this case)
private readonly IShippingStrategyFactory _shippingStrategyFactory;
public Program(IShippingStrategyFactory shippingStrategyFactory)
{
_shippingStrategyFactory = shippingStrategyFactory;
}
public int DoTheWork(Order order)
{
// assign properties just as an example
order.ShippingMethod = "Fedex";
order.OrderTotal = 90;
order.OrderWeight = 12;
order.OrderZipCode = 98109;
IShippingStrategy shippingStrategy = _shippingStrategyFactory.GetShippingStrategy(order);
int shippingCost = shippingStrategy.CalculateShippingCost(order);
return shippingCost;
}
}
Зачем брать bruden для создания фабрики (добавив дополнительный слой), когда мы можем вводить интерфейс непосредственно туда, где нам нужно его использовать?
Я думаю, вам не нужна еще одна статья о фабричной схеме, но короткий всеобъемлющий ответ. Поэтому я хотел бы остановиться на двух вещах.
Чаще всего вы должны настроить свой корневой каталог, в котором вы в основном говорите...
"Если кто-то хочет
IAnyService
, он должен получитьMyAnyServiceImplementation
".
Это исправлено для вашего приложения. После настройки ваш контейнер инъекций зависимостей будет обслуживать экземпляры классов, которые вы зарегистрировали, но вы не должны пытаться снова настроить этот контейнер. Это идеально подходит для гибкости запуска, например, для регистрации реализации компонентов доступа к данным с помощью конфигурации приложения. Сказать...
"Если кто-то хочет
IUserRepository
, он должен получитьMsSqlUserRepository
потому что мы работаем с сервером MSSQL".
Конечно, наличие этого "неизменяемого" корня композиции ограничивает возможности выбора реализации во время выполнения в зависимости от состояния приложений.
Вместо этого вы можете вводить класс, который принимает решение о текущем состоянии, которое должна выполнять реализация сервиса. Валидация данных является типичным сценарием для этого шаблона, поскольку в вашей системе могут быть разные правила для разных объектов. Здесь слово "шаблон правила" или "шаблон стратегии".
Подумайте о долгоживущем экземпляре класса, например, о представлении (пользовательском интерфейсе) или любом подключенном к нему классе (например, в режиме просмотра или контроллере). Пока пользователь активен в представлении, класс жив. Например, введя экземпляр класса в конструктор контроллера представлений, вы держите активный экземпляр его, пока жив.
Скажем, вы хотите использовать репозиторий данных для подключения к базе данных, например. Эти вызовы доступа к базе данных должны быть короткими, и вы не хотите, чтобы соединения открывались в течение длительного времени. С фабрикой репозитория вы можете очень точно контролировать время жизни и убедиться, что класс удален после его использования:
using (var repository = new _factory.CreateRepository(...))
{
return repository.GetAnything();
}
При этом очень легкий класс - завод - вводится и живет до тех пор, пока живет контроллер. Тяжелые классы - вещи, связанные с соединением, - не должны жить долго и просто создаваться, когда это необходимо.
Фактически, есть вероятность, что репозиторий вообще не создается, если нет необходимости загружать данные (например, из-за хиджа в верхнем кэше). Если бы вы прямо ввели хранилище, вы гарантировали бы, что один длинный живой экземпляр живет в памяти в каждом случае.
IUserRepository
о котором вы говорили. Для меня преимущество, которое мы можем получить от использования фабричного шаблона, состоит в том, что у нас есть возможность использовать различные компоненты доступа к данным в одном приложении. Например, если у нас есть MsSqlUserRepository
и AzurelUserRepository
мы можем использовать их оба в одном приложении, используя фабричный шаблон, что невозможно, если мы напрямую IUserRepository
верно?
MsSqlUserRepository
, если вы настроены для синхронизации с Azure, используйте AzureUserRepository
. Как только процесс запущен, вы должны жить с ним. Наличие фабрики позволяет вам переключаться между этими двумя во время выполнения, но я думаю, что доступ к данным не лучший вариант для этого, потому что он вряд ли будет таким общим. Может быть, вы имели в виду то же самое, я не совсем уверен, правильно ли я понял «в том же приложении».
Если вы проверите код для фабрики, вы увидите, что в зависимости от метода ShippingMethod заказа другая фабрика IShippingStrategy возвращается. Поскольку метод ShippingMethod известен только после того, как DoTheWork был назван невозможным для внедрения правильной реализации при построении класса (и для одного и того же класса могут потребоваться разные реализации для разных заказов).