Читайте также:
|
|
и адаптировать иерархически структурированный объект. Например, подкласс DirectoryTreeDisplay при их реализации будет осуществлять доступ к структуре каталогов файловой системы. DirectoryTreeDi splay специализирует узкий интерфейс таким образом, чтобы он мог отображать структуру каталогов, составленную из объектов File SystemEntity;
использование объектов-уполномоченных. При таком подходе TreeDisplay переадресует запросы на доступ к иерархической структуре объекту-уполномоченному. TreeDisplay может реализовывать различные стратегии адаптации, подставляя разных уполномоченных. Например, предположим, что существует класс DirectoryBrowser, который использует TreeDisplay. DirectoryBrowser может быть уполномоченным для адаптации TreeDisplay к иерархической структуре каталогов. В динамически типизированных языках вроде Smalltalk или Objective С такой подход требует интерфейса для регистрации уполномоченного в адаптере. Тогда TreeDisplay просто переадресует запросы уполномоченному. В системе NEXTSTEP [Add94] этот подход активно используется для уменьшения числа подклассов.
В статически типизированных языках вроде C++ требуется явно определять интерфейс для уполномоченного. Специфицировать такой интерфейс можно, поместив «узкий» интерфейс, который необходим классу TreeDisplay, в абстрактный класс TreeAccessorDelegate. После этого допустимо добавить этот интерфейс к выбранному уполномоченному - в данном случае DirectoryBrowser - с помощью наследования. Если у DirectoryBrowser еще нет существующего родительского класса, то воспользуемся одиночным наследованием, если есть - множественным. Подобное смешивание классов проще, чем добавление нового подкласса и реализация его операций по отдельности;
- параметризованные адаптеры. Обычно в Smalltalk для поддержки сменных адаптеров параметризуют адаптер одним или несколькими блоками. Конструкция блока поддерживает адаптацию без порождения подклассов. Блок может адаптировать запрос, а адаптер может хранить блок для каждого отдельного запроса. В нашем примере это означает, что TreeDisplay хранит один блок для преобразования узла в GraphicNode, а другой - для доступа к потомкам узла.
Например, чтобы создать класс TreeDisplay для отображения иерархии каталогов, мы пишем:
directoryDisplay:=
(TreeDisplay on: treeRoot) getChiIdrenBlock:
[:node | node getSubdirectories] createGraphicNodeBlock:
[:node | node createGraphicNode].
Если вы встраиваете интерфейс адаптации в класс, то этот способ дает удобную альтернативу подклассам.
Пример кода
Приведем краткий обзор реализации адаптеров класса и объекта для примера, обсуждавшегося в разделе «Мотивация», при этом начнем с классов Shape и Text View:
class Shape { public:
Shape();
virtual void BoundingBox(
Points bottomLeft, Point& topRight
) const;
virtual Manipulator* CreateManipulator() const;
class TextView { public:
TextView();
void GetOrigin(Coord& x, Coords y) const;
Дата добавления: 2015-09-11; просмотров: 78 | Поможем написать вашу работу | Нарушение авторских прав |