Выбор абстрактного класса Java или класса Static Utility
Я реализую несколько стратегий (шаблон стратегии), которые имеют некоторое общее поведение, и я не знаю, где должны жить общие операции.
- Предполагая, что я 1 контекст и 3 стратегии, некоторые операции, используемые в стратегиях, являются общими, некоторые необходимы только 2 другим, а только 1 из стратегий.
- Не существует общего состояния на уровне участника, поэтому единственные операции фактически не сохраняют состояния.
- Целью этих операций является поддержка форматирования состояния в файл, например помощник вида.
Вариант 1. Создание класса AbstractStrategy
- Я использую Java, так что это сразу уберет использование этой функции в будущем.
- Наследование имеет тенденцию к результату. в структуре горного хребта.
- Операции будут окончательными.
Вариант 2. Создание класса статических помощников Util
- Гибкий, но чувствует себя как запах кода по какой-то причине.
- Не ребристый
Любые рекомендации или предпочтения?
Обратите внимание, что уровень, на котором я работаю, это уровень Стратегии, а не Уровень контекста (см. Ссылку в Википедии).
4 ответа
Есть одна причина... одна огромная причина... использовать статический класс Util над абстрактным классом или интерфейсом.
Таким образом, вы можете добавить больше методов позже.
С помощью абстрактного класса или интерфейса любое изменение, которое вы вносите в этот класс / интерфейс, должно быть изменено во всех классах, которые наследуют его. Это особенно проблематично, если вы пишете публичный API.
Инфраструктура Java имеет классы утилит со статическими методами, разбросанными по всему. Самые известные из них находятся в java.util
пакет: Collections
а также Arrays
,
Есть еще один вариант в дополнение к двум, которые вы перечислили:
Мне кажется, что вы хотите какую-то композицию, в которой вы можете использовать только те функции, которые вам нужны. Возможно, вы могли бы упаковать свои операции, используя шаблон команд, а затем собрать свои стратегии из них?
Преимущества:
- Стратегия наследования не требуется.
- Стратегии не будут иметь видимости на неиспользуемые / скрытые "общие методы".
- Нет статического служебного класса с беспорядком (возможно) несвязанных методов.
- Проще провести модульное тестирование - операции можно тестировать изолированно.
- Простой общий класс стратегии, который перебирает операции.
Недостатки:
- Дополнительные занятия
- Операции должны соответствовать общему командному интерфейсу, который может быть ограничительным.
- Может быть излишним для очень простых операций - какими могут быть ваши форматеры.
Если он объявлен как абстрактный, люди могут догадаться, что он предназначен для расширения. Поэтому объявлять приватного конструктора - лучшая идея.
Есть много способов достичь этого.
Используйте абстрактный класс и превращайте переменные части выполнения в абстрактные методы => Некоторые стратегии реализуют все операции (переопределяя абстрактные методы), в то время как другие могут пропускать необязательные. Обратите внимание, что в этом случае необязательные операции могут быть пустыми подключаемыми методами, а не абстрактными методами. Таким образом вы избежите необходимости реализовывать эти операции как пустые методы в подклассе.
Используйте реальный интерфейс "Стратегия" (с методом execute, как в статье в Википедии, на которую вы указали). Затем клиентский класс будет обеспечен реализацией стратегии (может быть анонимным внутренним классом или фактически полноценным классом стратегии).
Первый более простой, но более жесткий: если вам нужно изменить количество операций (особенно абстрактных), необходимо обновить все подклассы.
Второй вариант более гибкий, но вам нужно будет найти способ "делиться" общими операциями между различными стратегиями путем делегирования или использования статических служебных методов.