Мое понимание фабрики заключается в том, что она инкапсулирует экземпляры конкретных классов, которые все наследуют общий абстрактный класс или интерфейс. Это позволяет отделить клиента от процесса определения того, какой конкретный класс создать, что, в свою очередь, означает, что вы можете добавлять или удалять конкретные классы из своей программы без необходимости изменения кода клиента. Возможно, вам придется изменить фабрику, но фабрика «специально построена» и на самом деле имеет только одну причину для изменения — добавлен/удален конкретный класс.
Я создал несколько классов, которые на самом деле инкапсулируют создание объектов, но по другой причине: объекты трудно создавать. На данный момент я называю эти классы «фабриками», но я обеспокоен тем, что это может быть неправильным названием и сбить с толку других программистов, которые могут посмотреть на мой код. Мои «фабричные» классы не решают, какой конкретный класс создавать, они гарантируют, что серия объектов будет создана в правильном порядке и что правильные классы будут переданы в правильные конструкторы, когда я вызову new()
.
Например, для проекта MVVM, над которым я работаю, я написал класс, чтобы убедиться, что мой экземпляр SetupView
создается правильно. Это выглядит примерно так:
public class SetupViewFactory
{
public SetupView CreateView(DatabaseModel databaseModel, SettingsModel settingsModel, ViewUtilities viewUtilities)
{
var setupViewModel = new SetupViewModel(databaseModel, settingsModel, viewUtilities);
var setupView = new SetupView();
setupView.DataContext = setupViewModel;
return setupView;
}
}
Не путает ли это название "фабрика"? Он не делает выбор между несколькими возможными конкретными классами, и его тип возвращаемого значения не является интерфейсом или абстрактным типом, но он инкапсулирует создание экземпляра объекта.
Если это не "фабрика", то что?
Изменить
Некоторые люди предположили, что на самом деле это шаблон Builder.
Определение шаблона Builder от dofactory выглядит следующим образом:
Отделите построение сложного объекта от его представления, чтобы один и тот же процесс построения мог создавать разные представления.
Это тоже кажется немного натянутым. Что меня беспокоит, так это «разные представления». Моя цель не в том, чтобы абстрагироваться от процесса построения представления (не то, чтобы это не было достойной целью). Я просто пытаюсь поместить логику для создания определенного представления в одном месте, так что, если какие-либо ингредиенты или процесс создания этого представления изменятся, мне нужно будет изменить только этот один класс. Шаблон компоновщика действительно, кажется, говорит: «Давайте создадим общий процесс для создания представлений, затем вы сможете следовать этому же базовому процессу для любого создаваемого вами представления». Мило, но я здесь не этим занимаюсь.
Изменить 2
Я только что нашел интересный пример в статье Википедии о внедрении зависимостей.
В разделе "Введенная вручную зависимость" он содержит следующий класс:
public class CarFactory {
public static Car buildCar() {
return new Car(new SimpleEngine());
}
}
Это почти в точности то, что я использую (и нет, я не писал вики-статью :)).
Интересно, что это комментарий, следующий за этим кодом:
В приведенном выше коде завод берет на себя ответственность за сборку автомобиля и впрыскивает двигатель в автомобиль. Это освобождает автомобиль от знания о том, как создать двигатель, хотя теперь CarFactory должен знать о конструкции двигателя. Можно было бы создать EngineFactory, но это просто создает зависимости между фабриками. Таким образом, проблема остается, но, по крайней мере, она перенесена в объекты factory или builder. [мой акцент]
Итак, это говорит мне о том, что, по крайней мере, я не единственный, кто думал о создании класса, помогающего внедрять вещи в другой класс, и я не единственный, кто пытался назвать этот класс фабрикой.