Снова к нашей игре.
Пусть юнитам (CUnit) в нашей нужно бывает окружать себя простой рамкой. Хорошим решением будет создать новый подкласс - который будет окружать юнит рамкой (CBorderedUnit). А иногда нужна прокрутка, например если строение слишком большое, чтобы его отражать полностью. Тогда создаем подкласс - который реализует прокрутку (CScrollUnit). Ну, конечно, если понадобится прокрутка и простая рамка, то породим класс (CBorderedScrollUnit) - множественным наследованием. Или один от другого. Только это не решит проблемы, поскольку вот еще видел я в Visual... такую рамочку вокруг компонента, которая такая из восьми черных квадратиков, она еще позволяет изменять размер и положение (ах, Малевич, не поняли его в России, а какое влияние на мир оказал). Эта рамка нужна больше жизни. И теперь мы получаем еще пачку классов CDesing, CDesignBordered, CDesignBordered - и так далее.
В общем, решение неудачное.
А вот решение получше: Пусть всякие рамки компонетам добавляет другой компонент-контейнер, который все запросы к себе исправно перенаправляет лежащему в нем объекту, а от себя добавляет только минимальное дополнительное поведение. При этом контейнер видит базовый класс компонента, и если мы положим в контейнер потомок базового класса или другой похожий контейнер, то он не заметит подмены. Это как в дельфях Вы выкладываете на форму панель, на панель скроллер, на скроллер картинку. О такой феньке я рассказывал в "Стили и идиомы": "Шаг 7 - Интерфейсы. Интерфейсные указатели", там это называлось интерфейсным указателем, а здесь - декоратором; кроме того, требуется порождать компонент и его декоратор от одного базового класса, чтобы уже ИХ контейнер так же не замечал подмены.
// Общий предок с функцией отрисовки. class CUnit { public: virtual void draw (); }; // Какой-то конкретный юнит со своей отрисовкой. class CSomeUnit : public CUnit { public: void draw (); }; // базовый декоратор, перенаправляет вызовы class CDecorator : public CUnit { public: CUnit* m_unit; // Все декораторы перенаправляют вызовы как минимум void draw () {m_unit->draw(); }; }; //Конкретный декоратор, добавляет собственное поведение class CBorderDecorator : public CDecorator { // вот оно, собственное поведение void drawBorder (); public: void draw () { // сначала вызывается общее поведение CDecorator::draw(); // а теперь частное. drawBorder (); }; };