Как быть с такой иерархией

Рейтинг: 1Ответов: 1Опубликовано: 07.03.2015

У меня есть следующие базовые классы с соответствующими методами, представляющие собой элементы графического интерфейса: EventObjprocessEvent, RepaintObjrepaint, ContainerObjaddObj. Однако некоторым другим классам, использующим указанные классы, нужны объекты, которые могут выполнять сразу несколько действий, например, processEvent и repaint вместе, и, возможно, их перегрузить. Для этого логичным представляется создать ещё несколько классов: EventAndRepaintObj, ContainerAndEventObj ... с помощью множественного наследования или композиции с делегированием вызовов методов. Меня смущает, что классов получается много (2^n - 1), особенно если ещё потребуется добавить базовые классы. Такая ситуация нормальна? Если нет, то как можно исправить?

Почему мне не подходит паттерн «Стратегия». Согласно Википедии, мотивы использования паттерна:

Программа должна обеспечивать различные варианты алгоритма или поведения
Нужно изменять поведение каждого экземпляра класса
Необходимо изменять поведение объектов на стадии выполнения

Мне ничего из этого не надо. Кроме того, из того же источника

Вызов всех алгоритмов должен осуществляться стандартным образом (все они должны иметь одинаковый интерфейс).

В моём случае у методов интерфейс, очевидно, различается. (processEvent(Event&), addObj(Obj*), repaint() ) К тому же, «стратегию» можно сделать только одну (либо одно действие, либо другое), а тут необходимо, чтобы объект мог выполнять сразу несколько действий.

Возможно, я ошибаюсь, но тогда необходим более подробный ответ, а не просто «используйте паттерн "стратегия"».

По поводу паттерна по ссылке @VadimTukaev — он несколько отличается от обычной «Стратегии». Применительно к моему вопросу — это поместить в один класс-обертку ObjectWrap по одному объекту базовых классов EventObj, RepaintObj, ContainerObj или их заглушки, и все соответствующие методы processEvent, repaint, addObj, которые вызывают методы объектов базовых классов. Ну и ещё, наверное, различные isEventObj, isRepaintObj. Я вижу следующие минусы: один класс «знает» про все методы и объекты, невозможность контроля типов компилятором при передаче объекта ObjectWrap (нельзя сказать, есть ли там объект EventObj). И я так понимаю, если нужно не просто скомбинировать два объекта, но и добавить какие-то дополнительные действия (например, вызывать repaint при вызове addObj), то новый класс все равно придется создавать.

Вообще, наверное, проще было бы использовать объект шаблонного класса, который наследуется от всех аргументов шаблона. Однако, непонятно тогда, как в конструкторе передать аргументы конструкторам базовых классов. Разве что использовать отложенную инициализацию, а конструкторы сделать пустыми.

Ответы

▲ 2

Почему мне не подходит паттерн «Стратегия». Согласно Википедии, мотивы использования паттерна:

Программа должна обеспечивать различные варианты алгоритма или поведения Нужно изменять поведение каждого экземпляра класса Необходимо изменять поведение объектов на стадии выполнения

Мне ничего из этого не надо.

Вам надо первое и второе. Третье - опционально, не надо так не надо. Когда что-то есть, а оно Вам не надо - это ведь намного лучше ситуация, чем когда что-то надо, а его нету.

Я только лишний раз убедился, что Вы не представляете смысл паттерна "Стратегия". Не факт, что Вам нужен именно он, но факт, что Вы даже не рассматривали его толком. Очень советую посмотреть видео по ссылке, которую я дал. Там объясняется очень подробно и интересно. Причем дается три способа реализации паттерна "Стратегия". Условно их можно назвать наивный, простой и канонический. Судя по всему, канонический Вам действительно избыточен, а вот какой-то из двух оставшихся вполне может пригодиться. Если посмотрите и скажете, что Вам оно все же не надо, и подробно объясните, почему - будем думать дальше.