Студопедия
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Реализация

Читайте также:
  1. IV.Реализация продукции
  2. RAIDS Практическая реализация
  3. Вымирание - как реализация идеала
  4. Глава 9. РЕАЛИЗАЦИЯ ИМУЩЕСТВА ДОЛЖНИКА НА ТОРГАХ
  5. Злоупотребление правом, реализация интереса и правореализация: проблемы соотношения.
  6. Интерфейс и реализация
  7. Конкретная ситуация 3 Реализация стратегических изменений
  8. Наиболее эффективная реализация божественной сути человека происходит в отношениях с людьми, в построении уважительных, любящих, дружеских отношений со всеми окружающими.
  9. Правомерное поведение, реализация права.
  10. Разработка и реализация маркетинговых проектов и программ

При реализации паттерна заместитель можно использовать следующие воз­можности языка:

а перегрузку оператора доступа к членам в C++. Язык C++ поддерживает пе­регрузку оператора доступа к членам класса ->. Это позволяет производить дополнительные действия при любом разыменовании указателя на объект. Для реализации некоторых видов заместителей это оказывается полезно, поскольку заместитель ведет себя аналогично указателю. В следующем примере показано, как воспользоваться данным приемом для реализации виртуального заместителя imagePtr:

class Image;

extern Image* LoadAnImageFile(const char*); // внешняя функция

class ImagePtr { public:

ImagePtr (const char* imageFile);

virtual -ImagePtr ();

virtual Image* operator-> ();

virtual Image& operator* (); private:

Image* Loadlmage (); private:

Image* _image;

const char* _imageFile;

ImagePtr::ImagePtr (const char* theImageFile) _imageFile = theImageFile; _image = 0;


"1 "1

 


 

Структурные паттерны

Image* ImagePtr::LoadImage () {

if (_image ==0) {

_image = LoadAnlmageFile(_imageFile);

}

return _image; }

Перегруженные операторы -> и * используют операцию Loadlmage для возврата клиенту изображения, хранящегося в переменной _image (при не­обходимости загрузив его):

Image* ImagePtr::operator-> () { return Loadlmage();

Image& ImagePtr::operator* () {

return *LoadImage(); }

Такой подход позволяет вызывать операции объекта Image через объекты ImagePtr, не заботясь о том, что они не являются частью интерфейса дан­ного класса:

ImagePtr image = ImagePtr("anlmageFileName"); image->Draw(Point (50, 100));

// (image.operator->())->Draw(Point(50, 100))

Обратите внимание, что заместитель изображения ведет себя подобно ука­зателю, но не объявлен как указатель на Image. Это означает, что использо­вать его в точности как настоящий указатель на Image нельзя. Поэтому при таком подходе клиентам следует трактовать объекты Image и ImagePtr по-разному.

Перегрузка оператора доступа - лучшее решение далеко не для всех видов заместителей. Некоторым из них должно быть точно известно, какая опера­ция вызывается, а в таких случаях перегрузка оператора доступа не работает. Рассмотрим пример виртуального заместителя, обсуждавшийся в разделе «Мотивация». Изображение нужно загружать в точно определенное вре­мя - при вызове операции Draw, а не при каждом обращении к нему. Пере­грузка оператора доступа не позволяет различить подобные случаи. В такой ситуации придется вручную реализовать каждую операцию заместителя, переадресующую запрос субъекту.

Обычно все эти операции очень похожи друг на друга, как видно из приме­ра кода в одноименном разделе. Они проверяют, что запрос корректен, что объект-адресат существует и т.д., а потом уже перенаправляют ему запрос. Писать этот код снова и снова надоедает. Поэтому нередко для его автомаА тической генерации используют препроцессор;

а метод doesNotUnderstand в Smalltalk. В языке Smalltalk есть возможность, по­зволяющая автоматически поддержать переадресацию запросов. При отправ­лении клиентом сообщения, для которого у получателя нет соответствующе­го метода, Smalltalk вызывает метод doesNotUnderstand: aMessage.


 

Паттерн Proxy

Заместитель может переопределить doesNotUnderstand так, что сообще­ние будет переадресовано субъекту.

Дабы гарантировать, что запрос будет перенаправлен субъекту, а не просто тихо поглощен заместителем, класс Proxy можно определить так, что он не станет понимать никаких сообщений. Smalltalk позволяет это сделать, надо лишь, чтобы у Proxy не было суперкласса1.

Главный недостаток метода doesNotUnderstand: в том, что в большин­стве Smalltalk-систем имеется несколько специальных сообщений, обраба­тываемых непосредственно виртуальной машиной, а в этом случае стандарт­ный механизм поиска методов обходится. Правда, единственной такой операцией, написанной в классе Ob j ect (следовательно, могущей затронуть заместителей), является тождество ==.

Если вы собираетесь применять doesNotUnderstand: для реализация заместителя, то должны как-то решить вышеописанную проблему. Нельзя же ожидать, что совпадение заместителей - это то же самое, что и совпаде­ние реальных субъектов. К сожалению, doesNotUnderstand: изначально создавался для обработки ошибок, а не для построения заместителей, по­этому его быстродействие оставляет желать лучшего;

а заместителю не всегда должен быть известен тип реального объекта. Если класс Proxy может работать с субъектом только через его абстрактный ин­терфейс, то не нужно создавать Proxy для каждого класса реального субъек­та Real Sub j ect; заместитель может обращаться к любому из них единооб­разно. Но если заместитель должен инстанцировать реальных субъектов (как обстоит дело в случае виртуальных заместителей), то знание конкрет­ного класса обязательно.

К проблемам реализации можно отнести и решение вопроса о том, как обра­щаться к еще не инстанцированному субъекту. Некоторые заместители должны обращаться к своим субъектам вне зависимости от того, где они находятся - дис­ке или в памяти. Это означает, что нужно использовать какую-то форму не зави­сящих от адресного пространства идентификаторов объектов. В разделе «Моти­вация» для этой цели использовалось имя файла.

Пример кода

В коде реализовано два вида заместителей: виртуальный, описанный в разде­ле «Мотивация», и реализованный с помощью метода doesNotUnderstand:.2

а виртуальный заместитель. В классе Graphic определен интерфейс для гра­фических объектов:

class Graphic { public:

virtual -Graphic();

1 Эта техника используется при реализации распределенных объектов в системе NEXTSTEP [Add94]
(точнее, в классе NXProxy). Только там переопределяется метод forward - эквивалент описанного
только что приема в Smalltalk.

2 Еще один вид заместителя дает паттерн итератор.


 

Структурные паттерны

virtual void Draw(const Point& at) = 0; virtual void HandleMouse (Event& event) = 0;

virtual const Point& GetExtent() = 0;

virtual void Load(istream& from) = 0; virtual void Save(ostream& to) = 0; protected:

Graphic();

Класс Image реализует интерфейс Graphic для отображения файлов изоб­ражений. В нем замещена операция HandleMouse, посредством которой пользователь может интерактивно изменять размер изображения:

class Image: public Graphic { public:

Image(const char* file); // загрузка изображения из файла

virtual ~Image();

virtual void Draw(const Point& at); virtual void HandleMouse(Event& event);

virtual const Point& GetExtent();

virtual void Load(istream& from); virtual void Save(ostream& to); private: //...

Класс imageProxy имеет тот же интерфейс, что и Image:

class ImageProxy: public Graphic { public:

ImageProxy(const char* imageFile);

virtual ~ImageProxy();

virtual void Draw(const Point& at); virtual void HandleMouse(Event& event);

virtual const Points GetExtent();

virtual void Load(istream& from);

virtual void Save(ostream& to); protected:

Image* GetlmageO; private:

Image* _image;

Point _extent;

char* _fileName; i.




Дата добавления: 2015-09-11; просмотров: 63 | Поможем написать вашу работу | Нарушение авторских прав

Мотивация | Структурные паттерны | Структурные паттерны | Структурные паттерны | Назначение | Паттерн Flyweight | Структурные паттерны | Применимость | Реализация | Паттерн Flyweight |


lektsii.net - Лекции.Нет - 2014-2025 год. (0.008 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав