Шаг 6 - Адаптер

Предположим, что интерфейс Вашей системы управляет графическими объектами через некий общий интерфейс, для чего все объекты порождаются от базового класса 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. На диаграмме классов я употребляю более абстрактные имена классов, наподобие клиент или адаптер.

6_1.gif (7147 b)


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Albert Makhmutov - 07.07.2001