Мне нужно принять следующее дизайнерское решение - столкнуться с ним во второй раз, поэтому я надеюсь, что я не единственный ...
У меня есть различные классы команд, которые представляют некоторые действия. Каждый класс Command (существует множество, скажем, SleepCommand, RunCommand, MeasureCommand) имеет разные параметры со значениями по умолчанию и т. Д., Но в конце каждый имеет метод generate()
, который возвращает некоторое упакованное представление.
Теперь у меня также есть класс CommandSequence, который объединяет много команд в списке. У него есть собственный метод generate (), который выполняет некоторую пользовательскую работу, запускает generate()
для всех команд в своем списке, добавляет свои собственные элементы и т. Д.
У меня есть сомнения относительно того, как создавать эти объекты команд. Есть несколько альтернатив:
(1) Позволяет пользователю создавать экземпляры различных объектов Command и просто вызывать метод add_command () для CommandSequence
(2) Создайте «фабричный метод» в CommandSequence для каждой из возможных команд. Методы фабрики принимают аргументы команды и передают их конструктору команды.
(3) Поскольку метод (2) дублирует код (списки инициализации конструктора объектов), я могу просто заставить все фабричные методы принимать *args, **kwargs
и передавать их объектам.
Теперь подход (1) не дублирует код, но предоставляет пользователю множество классов Command. В отличие от (2) код пользователя более подробный:
# seq is a CommandSequence object
seq.add_command(SleepCommand(time='10 ms', wakeup_alarm=False))
вместо:
seq.sleep(time='10 ms', wakeup_alarm=False)
Поскольку я создаю своего рода DSL, краткость и ясность кода пользователя очень важны для меня. Я могу использовать метод (3), чтобы сэкономить на дублировании кода, но затем, где разместить документацию классов Command - в фабричных методах или в самих конструкторах классов.
Я что-то упустил здесь? Как бы вы подошли к этому?