Так что у меня есть фабрика, которая создает объекты разных классов. Все возможные классы происходят от абстрактного предка. Фабрика имеет файл конфигурации (синтаксис JSON) и решает, какой класс создать, в зависимости от конфигурации пользователя.
Чтобы добиться этого, фабрика использует boost :: property_tree для JSON-анализа. Он идет по дереву и решает, какой конкретный объект создать.
Однако у объектов-продуктов есть много полей (атрибутов). В зависимости от конкретного класса, объект имеет около 5-10 атрибутов, в будущем может быть даже больше.
Поэтому я не уверен, как должен выглядеть конструктор объектов. Я могу придумать два решения:
1) Конструктор продукта ожидает каждый атрибут в качестве параметра, поэтому у конструктора будет более 10 параметров. Это будет ужасно и приведет к длинным нечитаемым строкам кода. Однако преимущество заключается в том, что фабрика может анализировать JSON и вызывать конструктор с правильными параметрами. Класс продукта не должен знать, что он был создан из-за конфигурации JSON. Нет необходимости знать, что JSON или конфигурация задействованы вообще.
2) Конструктор продукта ожидает только один аргумент, объект property_tree. Затем он может разобрать необходимую информацию. Если информация в конфигурации отсутствует или выходит за границы, каждый класс продукта может реагировать должным образом. Фабрике не нужно знать, какие аргументы нужны нескольким продуктам. Завод также не должен знать, как реагировать в случае неправильной конфигурации. И интерфейс конструктора унифицирован и мал. Но, как недостаток, продукт должен извлекать необходимую информацию из JSON, поэтому он знает, как он построен.
Я склонен предпочесть решение 2). Однако я не уверен, что это хорошая фабричная модель. Как-то неправильно, сообщая продукту, что он создан с конфигурацией JSON. С другой стороны, новые продукты могут быть введены очень просто.
Есть мнения по этому поводу?
Ответы:
Я бы не стал использовать вариант 2, потому что тогда вы навсегда свернули конструкцию вашего объекта с анализом дерева свойств boost. Если вас устраивает класс, которому нужно столько параметров, вам должен быть удобен конструктор, которому нужно столько параметров, такова жизнь!
Если ваша основная задача - читабельность кода, вы можете использовать шаблон компоновщика, в основном это пробел c ++ / java из-за отсутствия именованных аргументов. Вы получите вещи, которые выглядят так:
Так что теперь MyObject будет иметь приватный конструктор, который вызывается в Builder :: build. Приятно то, что это будет единственное место, где вам когда-либо придется вызывать конструктор с 10 параметрами. Фабрика дерева свойств boost будет использовать построитель, и впоследствии, если вы захотите создать MyObject напрямую или из другого источника, вы должны пройти через построитель. Кроме того, компоновщик позволяет четко указывать каждый параметр при его передаче, чтобы он был более читабельным. Это, очевидно, добавляет некоторый шаблон, так что вам придется решить, стоит ли это того по сравнению с простым вызовом грязного конструктора или объединением некоторых ваших существующих параметров в структуры и т. Д. Просто добавив еще один параметр в таблицу.
https://en.wikipedia.org/wiki/Builder_pattern#C.2B.2B_Example
источник
НЕ используйте второй подход.
Это определенно не решение и приведет только к созданию экземпляров классов в вашей бизнес-логике, а не к той части вашего приложения, где находятся фабрики.
Или:
Если объект, который вы создаете, на самом деле не является классом, ответственным за хранение данных, вы должны попытаться изменить код и разделить большой класс на меньший.
источник
new
или конструирования объектов внутри вашей бизнес-логики, это не очень хороший дизайн. Чек « Не ищите вещей» говорит Мишко Хевери , который более подробно объясняет, почему заводской подход, о котором вы намекнули, плох с точки зрения как тестирования, так и чтения. Кроме того, ваш класс выглядит как объект данных, и для него обычно лучше иметь больше параметров, чем обычный класс обслуживания. Я не был бы слишком обеспокоен.Вариант 2 почти правильный.
Улучшенный вариант 2
Создайте «фронтальный» класс, задачей которого является взять этот объект JSON-структуры, выбрать биты и вызвать конструктор (ы) фабрики. Он берет то, что делает фабрика, и дает это клиенту.
По сути, «передний конец» говорит двум Бобам: «Я имею дело с отредактированными клиентами, поэтому инженеры не должны! У меня есть навыки работы с людьми!» Бедный Том. Если бы он только сказал: «Я отделил клиента от строительства. Этот результат - очень сплоченная фабрика»; он мог бы сохранить свою работу.
Слишком много доводов?
Не для клиента - общение переднего плана.
Передняя часть - заводская? Если не 10 параметров, то лучшее, что вы можете сделать, это отложить распаковку, если не оригинальную JSON, то немного DTO. Это лучше, чем передавать JSON на завод? Та же разница, что я говорю.
Я бы настоятельно рекомендовал передать отдельные параметры. Придерживайтесь цели чистой, сплоченной фабрики. Избегайте проблем ответа @DavidPacker.
Смягчение "слишком много аргументов"
Конструкторы класса или фабрики
Группировка аргументов переднего конца
источник