Читаем Объектно-ориентированный анализ и проектирование с примерами приложений на С++ полностью

Одно из наиболее интересных свойств сред разработки заключается в том, что, в случае удачной реализации, они стремятся набрать некую критическую массу функциональности и адаптируемости. Другими словами, если мы правильно выбрали основные абстракции и наделили библиотеку рядом хорошо взаимодействующих между собой механизмов, то вскоре обнаружим, что клиенты используют наш продукт для решения тех задач, о которых разработчики среды и не подозревали. После того, как определились основные схемы использования среды, имеет смысл сделать их формальной частью самой библиотеки. Признаком правильности конструкции среды разработки является возможность внедрения новых моделей поведения с помощью повторного использования уже существующих свойств продукта и без нарушения принципов его архитектуры.

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

Сделаем два допущения, касающихся этого механизма. Во-первых, клиент должен обеспечить потоки, в которые объекты будут записываться и считываться. Во-вторых, клиент обязан обеспечить объектам поведение, необходимое для направления в поток.

Для создания такого механизма есть два альтернативных подхода. Можно построить класс-примесь, обеспечивающий семантику "долгожития"; именно такой подход реализован во многих объектно-ориентированных базах данных. В качестве альтернативы можно создать класс, экземпляры которого выступают в качестве агентов, ответственных за перенаправление различных структур в поток. Для того, чтобы обосновать наш выбор, попробуем оценить преимущества и недостатки того и другого подхода.

Как оказалось, для выбранного очень простого механизма сохраняемости примесь не совсем подходит (зато она очень хорошо вписывается в архитектуру настоящей объектно-ориентированной базы данных). При использовании примеси пользователь должен сам добавить ее к своему классу, зачастую переопределив при этом некоторые служебные функции класса-примеси. В нашем случае, для такого простого механизма это окажется неэффективным, так как пользователю будет легче разработать свои средства, чем дорабатывать библиотечные. Таким образом, мы склоняемся ко второму решению, которое потребует от пользователя лишь создания экземпляра уже существующего класса.

Рис. 9-14 иллюстрирует работу такого механизма, продлевающего жизнь объектов за счет работы отдельного агента. Класс Persist является дружественным классу Queue; мы определяем эту связь внутри описания класса Queue следующим образом:

friend class Persist>;

В этом случае классы становятся дружественными только в момент инстан-цирования класса Queue. Внедрив подобные описания дружественности в каждый абстрактный базовый класс, мы обеспечиваем возможность использования Persist с любой структурой библиотеки.

Параметризованный класс Persist содержит операции записи и считывания put и get, а также функции для подключения потоков обмена данными. Мы можем определить данную абстракцию следующим образом:

template class Persist { public:

Persist(); Persist(iostream& input, iostream& output); virtual ~Persist(); virtual void setInputStream(iostream&); virtual void setOutputStream(iostream&); virtual void put(Structure&); virtual void get(Structure&);

protected:

iostream* inStreain; iostream* outStream;

};  

Рис. 9-14. Обеспечение сохраняемости с помощью агента.

Реализация данного класса зависит от того, является ли он дружественным классу Structure, который фигурирует в качестве аргумента шаблона. В частности, Persist зависит от наличия в структуре вспомогательных функций purge, cardinality, itemAt, lock, и unlock. Далее срабатывает однородность нашей библиотеки: поскольку каждый базовый класс Structure имеет подобные функции, то persist можно безо всяких изменений использовать для работы со всеми имеющимися в библиотеке структурами.

Рассмотрим в качестве примера реализацию функции Persist::put:

template void Persist::put(Structure& s) {

Перейти на страницу:

Похожие книги

Adobe Flash. Создание аркад, головоломок и других игр с помощью ActionScript
Adobe Flash. Создание аркад, головоломок и других игр с помощью ActionScript

Данная книга посвящена программированию игр с помощью ActionScript. Здесь вы найдете подробные указания, необходимые для создания самых разных игр – аркад, головоломок, загадок и даже игровых автоматов. В тексте приведены исходные коды программ и детальные, доступно изложенные инструкции. Базовые принципы программирования ActionScript рассматриваются на примере игр, однако вы без труда сможете применить полученные знания и для разработки неигровых проектов, таких как Web-дизайн и реклама. Рекомендации Гэри Розенцвейга помогут вам не только придумывать занимательные игры и размещать их на Web-сайте, но и оптимизировать скорость их работы, а также защищать свои творения от несанкционированного копирования. Представленный в книге код несложно изменить для использования в других программах.Книга предназначена для широкого круга читателей – создателей анимационных роликов, художников-оформителей, программистов и разработчиков Web-сайтов. Издание может также выступать в качестве практического пособия по изучению ActionScript.

Гэри Розенцвейг

Программирование, программы, базы данных / Программирование / Книги по IT