В нашем приложении Rails мы добавляем уведомления. Вот некоторые из них blocking
: Они останавливают прогресс любого ресурса, к которому они добавлены, потому что некоторая информация об этом ресурсе отсутствует.
Другие уведомления являются простыми уведомлениями и предоставляют только информацию.
Сегодня у меня была дискуссия с другим программистом в нашей команде. Я создал структуру наследования следующим образом:
Однако он предпочел бы, чтобы я просто добавлял blocking
в качестве метода логического возврата в каждом уведомлении и указывал список подклассов, которые блокируются внутри родительского класса уведомления.
Разница между этими подходами не очень большая; в моем подходе нет необходимости указывать этот список, сохраняя корневой класс чище. С другой стороны, особая логика, которая происходит Notification::Blocking
сейчас, тоже не очень велика.
Какая абстракция больше подходит для этой проблемы?
Ответы:
Вы хотите, чтобы базовые классы не знали о производных классах. Это вводит тесную связь и является головной болью обслуживания, потому что вы должны помнить, чтобы добавлять в список каждый раз, когда вы создаете новый производный класс.
Это также не позволит вам поместить класс Notification в повторно используемый пакет / сборку, если вы хотите использовать этот класс в нескольких проектах.
Если вы действительно хотите использовать один базовый класс, другой способ решить эту проблему - добавить виртуальное свойство или метод IsBlocking в базовый класс Notification. Производные классы могут затем переопределить это, чтобы вернуть истину или ложь. У вас будет единственное решение для класса без знания базового класса о производных классах.
источник
Это выглядит очень странно и является специфическим запахом кода.
Я хотел бы предоставить подклассы, если у вас есть различия в поведении между классами, и вы хотите обрабатывать все эти уведомления одинаково (то есть, используя полиморфизм ).
источник
В качестве противоположности существующим ответам, я бы предположил, что логическое свойство является наилучшим вариантом, если необходимо использовать режим, который должен изменяться динамически (например, через файл конфигурации, который дает список типов, которые должны блокироваться). а которые нет).
Тем не менее, лучшим дизайном даже в этой ситуации может быть использование объекта Decorator.
источник
Я бы сказал, что это зависит от того, что еще особенного в уведомлении о блокировке, хотя моя первая мысль - использовать «оба»:
Таким образом, вы можете использовать
n.Blocking
илиn is BlockingNotification
(все в псевдокоде), хотя, если вы собираетесь позволить классу реализовать контекстно-зависимоеBlocking
значение, видя, как вам придется проверять это значение каждый раз,BlockingNotification
класс становится менее полезенВ любом случае, я согласен с другими ответами, которые вы не хотите, чтобы реализация базового класса
Blocking
знала о производных классах.источник
Вместо создания двух базовых классов и нескольких экземпляров каждого, создайте один класс уведомлений с логическим значением, чтобы указать, является ли уведомление блокирующим, и любую другую информацию, необходимую для передачи уведомления пользователю.
Это позволяет вам использовать один набор кода для обработки и представления уведомлений и уменьшает сложность вашего кода.
источник