Предположим, что интерфейс Вашей системы управляет графическими объектами через некий общий интерфейс, для чего все объекты порождаются от базового класса CGraphic. В один момент Вы обнаруживаете, что Вам совершенно необходим некий сложный графический класс CComplex, разрабатывать который с нуля нет ни малейшего желания.
По счастью, похожий класс CAlien есть в библиотеке, которую недавно делали в соседнем отделе. Вы бежите туда с дискеткой, записываете код, смотрите и... и ничего хорошего. Он не наследует от CGraphic. Его логика вообще другая.
Печально, но не смертельно. Нужно CComplex породить в открытую от CGraphic и в закрытую от CAlien, а функции интерфейса CGraphic переопределить так, чтобы они просто вызывали соответствующие функции CAlien. Это будет адаптер класса. Или просто вложить экземпляр (или указатель, или ссылку на) CAlien внутрь класса CComplex, и так же вызывать его функции. Это будет адаптер объекта.
Следует сказать, что по заветам единственно верного учения Буча простое использование или агрегация эффективнее закрытого наследования -например потому, что указатель может указывать на экземпляр подкласса CAlien.
Пример кода:
// Это - чужак class CAlien { public: void doAlien (); }; // Это то, к чему нужно привести интерфейс class CGraphic { public: virtual void doNatural ()=0; }; // Класс наследует интерфейс от CGraphics // а реализацию берет из CAlien. class CComplex : public CGraphic { private: CAlien m_alien; public: void doNatural () { m_alien.doAlien(); }; };
Вот структура паттерна adapter. На диаграмме классов я употребляю более абстрактные имена классов, наподобие клиент или адаптер.