У меня есть приложение, которое принимает целое число в качестве ввода и на основе ввода вызывает статические методы различных классов. Каждый раз, когда добавляется новый номер, нам нужно добавить еще один случай и вызвать другой статический метод другого класса. Теперь в коммутаторе 50 дел, и каждый раз, когда мне нужно добавить еще одно дело, я содрогаюсь. Есть лучший способ сделать это.
Я немного подумал и придумал эту идею. Я использую шаблон стратегии. Вместо случая переключения у меня есть карта объектов стратегии с ключом, являющимся входным целым числом. Как только метод вызывается, он ищет объект и вызывает универсальный метод для объекта. Таким образом, я могу избежать использования конструкции switch switch.
Что вы думаете?
design-patterns
object-oriented-design
Каушик Чакраборты
источник
источник
switch
случай и вызывать уже существующий метод в вашей сложной системе, или вам нужно изобрести как метод, так и его вызов?Ответы:
Я люблю полиморфизм. Я люблю SOLID. Я люблю чисто объектно-ориентированное программирование. Я ненавижу видеть их с плохой репутацией, потому что они применяются догматически.
Вы не нашли веского основания для рефакторинга стратегии. Кстати, у рефакторинга есть имя. Это называется Заменить Условное Полиморфизмом .
Я нашел несколько полезных советов для вас от c2.com :
У вас есть переключатель на 50 ящиков, и вы можете создать 50 предметов. Ох и 50 строк строительного кода объекта. Это не прогресс. Почему бы нет? Потому что этот рефакторинг ничего не делает для уменьшения числа от 50. Этот рефакторинг используется, когда вы обнаружите, что вам нужно создать еще один оператор switch для того же ввода где-то еще. Вот когда этот рефакторинг помогает, потому что он превращает 100 обратно в 50.
Пока вы говорите о «переключателе», как будто он единственный, который у вас есть, я не рекомендую этого. Единственное преимущество рефакторинга сейчас заключается в том, что он снижает вероятность того, что какой-нибудь дурак скопирует и вставит ваш переключатель на 50 случаев.
Я рекомендую внимательно изучить эти 50 случаев, чтобы выявить общие черты. Я имею в виду 50? В самом деле? Вы уверены, что вам нужно так много дел? Возможно, вы пытаетесь сделать многое здесь.
источник
Карта только объектов стратегии, которая инициализируется в некоторой функции вашего кода, где у вас есть несколько строк кода, похожих на
требует от вас и ваших коллег реализации функций / стратегий, вызываемых в отдельных классах, более единообразным образом (поскольку все объекты стратегии должны будут реализовывать один и тот же интерфейс). Такой код часто немного более полон, чем
Тем не менее, он по-прежнему не освобождает вас от бремени редактирования этого файла кода всякий раз, когда необходимо добавить новый номер. Реальные преимущества этого подхода в другом:
инициализация карты теперь отделена от кода отправки, который фактически вызывает функцию, связанную с конкретным номером, и последний больше не содержит эти 50 повторений, это будет просто выглядеть
myMap[number].DoIt(someParameters)
. Таким образом, этот код отправки не нужно трогать всякий раз, когда приходит новый номер, и он может быть реализован в соответствии с принципом Open-Closed. Более того, когда вы получаете требования, в которых вам необходимо расширить сам код отправки, вам больше не придется менять 50 мест, а только одно.содержимое карты определяется во время выполнения (в то время как содержимое конструкции switch определяется до времени компиляции), так что это дает вам возможность сделать логику инициализации более гибкой или расширяемой.
Так что да, есть некоторые преимущества, и это, безусловно, шаг к более твердому коду. Однако, если это окупится рефакторингом, это то, что вам или вашей команде придется решать самостоятельно. Если вы не ожидаете, что код отправки будет изменен, логика инициализации будет изменена, и читаемость
switch
не будет реальной проблемой, то ваш рефакторинг может быть не так важен сейчас.источник
Doit1
,Doit2
и т.д. с однимDoit
методом , который имеет много различных реализаций.doTheThing()
метод входного символа. Тогда вам не нужно поддерживать карту.Я решительно поддерживаю стратегию, изложенную в ответе @DocBrown .
Я собираюсь предложить улучшение ответа.
Звонки
можно распространять. Вам не нужно возвращаться к тому же файлу, чтобы добавить другую стратегию, которая еще лучше придерживается принципа Open-Closed.
Скажем, вы реализуете
Strategy1
в файле Strategy1.cpp. Вы можете иметь следующий блок кода в нем.Вы можете повторить один и тот же код в каждом файле StategyN.cpp. Как видите, это будет много повторяющегося кода. Чтобы уменьшить дублирование кода, вы можете использовать шаблон, который можно поместить в файл, доступный для всех
Strategy
классов.После этого единственное, что вам нужно использовать в Strategy1.cpp:
Соответствующая строка в StrategyN.cpp:
Вы можете перенести использование шаблонов на другой уровень, используя шаблон класса для конкретных классов Стратегии.
А потом вместо
Strategy1
использованияConcreteStrategy<1>
.Измените вспомогательный класс для регистрации
Strategy
s:Измените код в Strateg1.cpp на:
Измените код в StrategN.cpp на:
источник