У меня есть вопрос о дизайне, который меня давно беспокоил, но я не могу найти хорошее (в смысле ООП) решение для этого.Язык C ++, и я продолжаю возвращаться к RTTI, который часто называют индикатором плохого дизайна.
Предположим, у нас есть набор модулей разных типов, реализованных как разные классы.Каждый тип модуля характеризуется определенным интерфейсом, однако реализация может отличаться.Таким образом, моей первой идеей было создать интерфейсный (чисто абстрактный) класс для каждого типа модуля (например, IModuleFoo, IModuleBar и т. Д.) И реализации в отдельных классах.Пока все хорошо.
class IModuleFoo {
public:
virtual void doFoo() = 0;
};
class IModuleBar {
public:
virtual void doBar() = 0;
};
С другой стороны, у нас есть набор (прикладных) классов, и каждый из них использует несколько таких модулей, но только через интерфейсы - даже сами модули могут использовать другиемодули.Однако все классы приложения будут использовать один и тот же пул модулей.Моя идея состояла в том, чтобы создать класс менеджера (ModuleManager) для всех модулей, классы приложений которого могут запрашивать нужные им типы модулей.Доступные модули (и конкретная реализация) устанавливаются во время инициализации менеджера и могут изменяться со временем (но это не является частью моего вопроса).
Поскольку число различных типов модулей наиболее вероятно> 10 и может увеличиваться со временем, мне кажется неуместным хранить ссылки (или указатели) на них отдельно.Кроме того, может быть несколько функций, которые менеджер должен вызывать во всех управляемых модулях.Таким образом, я создал другой интерфейс (IManagedModule) с тем преимуществом, что теперь я могу использовать контейнер (список, набор, что угодно) для IManagedModules, чтобы хранить их в диспетчере.
class IManagedModule {
public:
virtual void connect() = 0;
{ ... }
};
В результате модуль, которыйдолжен управляться должен наследоваться как от IManagedModule, так и от соответствующего интерфейса для его типа.
Но все становится ужасно, когда я думаю о ModuleManager.Можно предположить, что в каждый момент времени присутствует не более одного экземпляра каждого типа модуля.Таким образом, если бы можно было сделать что-то подобное (где manager является экземпляром ModuleManager), все было бы хорошо:
IModuleFoo* pFoo = manager.get(IModuleFoo);
Но я почти уверен, что это не так.Я также подумал о решении на основе шаблонов, например:
IModuleFoo* pFoo = manager.get<IModuleFoo>();
Это может сработать, но я понятия не имею, как найти нужный модуль в менеджере, если все, что у меня есть, это набор IManagedModules - то есть безиспользование RTTI, конечно.
Один из подходов состоит в том, чтобы предоставить IManagedModule виртуальный метод getId () , полагаться на реализации, использующие не неоднозначные идентификаторы для каждого типа модуля, и выполнять приведение указателей самостоятельно.,Но это просто изобретение колеса (а именно RTTI) и требует большой дисциплины в реализующих классах (предоставление правильных идентификаторов и т. Д.), Что нежелательно.
Короче говоря, вопрос в том, есть лина самом деле нет никакого способа обойти какой-то RTTI здесь, и в этом случае RTTI может даже быть допустимым решением или если может быть лучший (более чистый, безопасный, ...) дизайн, который демонстрирует такую же гибкость (например, слабая связь между классами приложений)а модульные классы ...)?Я что-то пропустил?