Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Приемы объектно-ориентированного проектирования...doc
Скачиваний:
24
Добавлен:
14.08.2019
Размер:
5.43 Mб
Скачать

В.2. Диаграмма объектов

На диаграмме объектов представлены только экземпляры. На ней показан мгновенный снимок объектов в паттерне проектирования. Объекты именуются «aSomething», где Something – это класс объекта.

Рис. В. 1. Нотация диаграмм классов: а) абстрактные и конкретные классы;

б) класс клиента участника (слева) и класс неявного клиента (справа);

в) отношения между классами; г) аннотация на псевдокоде.

Для обозначения объекта используется прямоугольник с закругленными углами (что несколько отличается от стандарта OMT), в котором имя объекта отделено от ссылок на другие объекты горизонтальной линией. Стрелки ведут к объектам, на которые ссылается данный. На рисунке В.2 приведен соответствующий пример.

Рис. В.2. Нотация диаграмм объектов

В.3. Диаграмма взаимодействий

Порядок исполнения запросов, которые объекты посылают друг другу, показан на диаграмме взаимодействий. Так, на рисунке В.3 представлено, как фигура добавляется к рисунку.

Рис. В.3. Нотация диаграмм взаимодействия

На диаграмме взаимодействий время откладывается сверху вниз. Сплошная вертикальная линия обозначает время жизни объекта. Соглашение об именовании объектов такое же, как на диаграммах объектов: имени класса предшествует буква «a» (например, aShape). Если объект еще не создан к начальному моменту времени, представленному на диаграмме, то его вертикальная линия идет пунктиром вплоть до момента создания.

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

На рисунке В.3 видно, что первый запрос, исходящий от aCreationTool, преследует целью создание объекта aLineShape. Затем aLineShape добавляется к объекту aDrawing с помощью операции Add, после чего aDrawing посылает самому себе запрос на обновление Refresh. Отметим, что частью операции Refresh является посылка объектом aDrawing запроса к aLineShape.

Приложение с. Базовые классы

В данном приложении документируются базовые классы, которые применялись в примерах кода на C++ в описаниях различных паттернов проектирования. Мы специально стремились сделать эти классы простыми и минимальными. Будут описаны следующие классы:

  • List – упорядоченный список объектов;

  • Iterator – интерфейс для последовательного доступа к объектам в агрегате;

  • ListIterator – итератор для обхода списка;

  • Point – точка с двумя координатами;

  • Rect – прямоугольник, стороны которого параллельны осям координат.

Некоторые появившиеся сравнительно недавно стандартные типы C++, возможно, реализованы еще не во всех компиляторах. В частности, если ваш компилятор не поддерживает тип bool, его можно определить самостоятельно:

typedef int bool;

const int true = 1;

const int false = 0;

C.1. List

Шаблон класса List представляет собой базовый контейнер для хранения упорядоченного списка объектов. В списке хранятся значения элементов, то есть он пригоден как для встроенных типов, так и для экземпляров классов. Например, запись List<int> объявляет список целых int. Но в большинстве паттернов в списке хранятся указатели на объекты, скажем, List<Glyph*>. Это позволяет использовать класс List для хранения разнородных объектов (точнее, указателей на них).

Для удобства в классе List есть синонимы для операций со стеком. Это позволяет явно использовать список в роли стека, не определяя дополнительного класса:

template <class Item>

class List {

public:

List(long size = DEFAULT_LIST_CAPACITY);

List(List&);

~List();

List& operator=(const List&);

long Count() const;

Item& Get(long index) const;

Item& First() const;

Item& Last() const;

bool Includes(const Item&) const;

void Append(const Item&);

void Prepend(const Item&);

void Remove(const Item&);

void RemoveLast();

void RemoveFirst();

void RemoveAll();

Item& Top() const;

void Push(const Item&);

Item& Pop();

};

В следующих разделах операции описываются более подробно.

Конструктор, деструктор, инициализация и присваивание

List(long size) – инициализирует список. Параметр size определяет начальное число элементов в списке.

List(List&) – замещает определяемый по умолчанию копирующий конструктор для правильной инициализации данных-членов.

~List() – освобождает внутренние структуры данных списка, но не элементы списка. Не предполагается, что у этого класса будут производные, поэтому деструктор не объявлен виртуальным.

List& operator=(const List&) – реализует операцию присваивания.

Доступ

Следующие операции обеспечивают доступ к элементам списка.

long Count() const – возвращает число объектов в списке.

Item& Get(long index) const – возвращение объекта с заданным индексом.

Item& First() const – возвращает первый объект в списке.

Item& Last() const – возвращение последнего объекта в списке.

Добавление

void Append(const Item&) – добавляет свой аргумент в конец списка.

void Prepend(const Item&) – добавляет свой аргумент в начало списка.

Удаление

void Remove(const Item&) – удаляет заданный элемент из списка. Для применения этой операции требуется, чтобы тип элементов поддерживал оператор сравнения на равенство ==.

void RemoveFirst() – удаляет первый элемент из списка.

void RemoveLast() – удаление последнего элемента из списка.

void RemoveAll() – удаляет все элементы из списка.

Интерфейс стека

Item& Тор() const – возвращает элемент, находящийся на вершине стека.

void Push(const Item&) – «заталкивает» элемент в стек.

Item& Pop() – «выталкивает» элемент с вершины стека.

С.2. Iterator

Iterator – это абстрактный класс, который определяет интерфейс обхода агрегата:

template <class Item>

class Iterator {

public:

virtual void First() = 0;

virtual void Next() = 0;

virtual bool IsDone() const = 0;

virtual Item CurrentItem() const = 0;

protected:

Iterator();

};

Операции делают следующее:

virtual void First() – позиционирует итератор на первый объект в агрегате.

virtual void Next() – позиционирует итератор на следующий по порядку объект.

virtual bool IsDone() const – возвращает true, если больше не осталось объектов.

virtual Item CurrentItem() const – возвращает объект, находящийся в текущей позиции.

С.З. ListIterator

ListIterator реализует интерфейс класса Iterator для обхода списка List. Его конструктор принимает в качестве аргумента список, который нужно обойти:

template <class Item>

class ListIterator : public Iterator<Item> {

public:

ListIterator(const List<Item>* aList);

virtual void First();

virtual void Next();

virtual bool IsDone() const;

virtual Item CurrentItem() const;

};

С.4. Point

Класс Point представляет точку на плоскости с помощью декартовых координат, поддерживает минимальный набор арифметических операций над векторами. Координаты точки определяются так:

typedef float Coord;

Операции класса Point не нуждаются в пояснениях:

class Point {

public:

static const Point Zero;

Point(Coord x = 0.0, Coord y = 0.0);

Coord X() const; void X(Coord x);

Coord Y() const; void Y(Coord y);

friend Point operator+(const Point&, const Point&);

friend Point operator-(const Point&, const Point&);

friend Point operator*(const Point&, const Point&);

friend Point operator/(const Point&, const Point&);

Point& operator+=(const Point&);

Point& operator-=(const Point&);

Point& operator*=(const Point&);

Point& operator/=(const Point&);

Point operator-();

friend bool operator==(const Point&, const Point&);

friend bool operator!=(const Point&, const Point&);

friend ostream& operator<<(ostream&, const Point&);

friend istream& operator>>(istream&, Point&);

};

Статический член Zero представляет начало координат Point(0, 0).

С.5. Rect

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

class Rect {

public:

static const Rect Zero;

Rect(Coord x, Coord y, Coord w, Coord h);

Rect(const Point& origin, const Point& extent);

Coord Width() const; void Width(Coord);

Coord Height() const; void Height(Coord);

Coord Left() const; void Left(Coord);

Coord Bottom() const; void Bottom(Coord);

Point& Origin() const; void Origin(const Point&);

Point& Extent() const; void Extent(const Point&);

void MoveTo(const Point&);

void MoveBy(const Point&);

bool IsEmpty() const;

bool Contains(const Point&) const;

};

Статический член Zero представляет вырожденный прямоугольник:

Rect(Point(0, 0), Point(0, 0));