#design-patterns #inheritance #constructor #types #factory
#шаблоны проектирования #наследование #constructor #типы #фабрика
Вопрос:
Всякий раз, когда я нахожусь в ситуации, когда у меня есть фабрика, возвращающая реализации абстрактного базового класса пользователю на основе некоторого параметра типа «низкого уровня», такого как протокол или формат внешнего ресурса, у меня всегда возникает соблазн преобразовать абстрактный класс в конкретный класс с внутренней «фабрикой стратегий», чтобы пользователи могли просто передавать тип реализации конструктору и работать с базовым классом напрямую.
Я заметил .Net framework решила реализовать сокет таким образом (вместо создания DatagramSocket вы передаете SocketType при построении). Каковы некоторые рекомендации по принятию решения, когда приемлемо сгладить иерархию в один конкретный класс, подобный этому?
Ответ №1:
Я думаю, что вопрос в том, «о какой части деталей низкого уровня должен знать клиент?».
Если вы выберете первое решение (абстрактный базовый класс), вы скроете больше деталей для клиентского класса. Таким образом, клиент может полностью игнорировать детали низкого уровня (протокол, формат внешнего ресурса.). Когда цель состоит в том, чтобы полностью скрыть детали реализаций и типы, используемые внутри этой реализации, я предпочитаю этот подход.
В противном случае, если клиенту уже известны некоторые детали низкоуровневой реализации (например, клиент знает, что сокет, который он будет использовать, является UDP, и он также хочет знать такого рода информацию), то подход абстрактного базового класса может быть заменен внутренней «фабрикой стратегий».
Ответ №2:
В духе «предпочитаю композицию наследованию» я всегда выбираю стратегию фабричный метод вместо наследования. Это дает мне пару преимуществ: * большую часть времени каждую стратегию можно тестировать изолированно, не заботясь о классе, который будет ее использовать. * в том же духе клиентский класс можно протестировать с помощью макетной стратегии * стратегии могут быть разработаны так, чтобы их можно было комбинировать, используя, например, шаблон декоратора, который обеспечивает большую гибкость, не вызывая взрыва подклассов.
В целом, если внешняя семантика всех ваших подклассов одинакова (как и должно быть), следуйте Стратегическому маршруту.