68
Наблюдатель (Observer) —
Паттерны программирования игр
чисто виртуальный интерфейс. Интерфейсы предпочти-
тельнее, чем конкретные классы с состоянием, так что
в целом нас все устраивает.
Но если мы
хотим
добавить немного стабильности
в класс
Observer
, мы сможем решить нашу проблему
выделения памяти, разделив список субъекта на потоки,
используя самих наблюдателей
. Вместо объекта, имею-
щего отдельный набор указателей, объекты-наблюдате-
ли становятся узлами в связанном списке (рис. 4.3).
Рис. 4.3
. Субъект указывает на связанный список наблюдателей
Чтобы реализовать это, сначала избавимся от масси-
ва в
Subject
и заменим его указателем на первый объ-
ект в списке наблюдателей:
class Subject
{
Subject()
: head_(NULL)
{}
// @…
private:
Observer* head_;
};
Затем расширим
Observer
указателем на следую-
щего наблюдателя в списке:
class Observer
{
friend class Subject;
public:
Observer()
: next_(NULL)
{}
Паттерны программирования игр
— Другой взгляд на паттерны проектирования
69
// …
private:
Observer* next_;
};
Мы также делаем
Subject
дружественным классом.
У субъекта есть специальное API для добавления и удале-
ния наблюдателей, но список, которым он будет управ-
лять, теперь находится внутри самого класса
Observer
.
Самый простой способ дать ему возможность изменять
этот список — сделать его дружественным.
Регистрация нового наблюдателя заключается в про-
стом добавлении его в список. Мы используем простой
вариант — вставим его в начало:
void Subject::addObserver(Observer* observer)
{
observer->next_ = head_;
head_ = observer;
}
Другой вариант — добавить его в конец связанного
списка. Это уже немного сложнее.
Subject
должен либо
пройти весь список, чтобы найти конец, либо сохранить
отдельный указатель
tail_
, который всегда указывает
на последний узел.
Добавление в начало списка проще, но имеет один
побочный эффект. Когда мы проходим список для от-
правки уведомления каждому наблюдателю,
первым
уведомление получает
последний
зарегистрированный
наблюдатель. А значит, если вы зарегистрируете наблю-
дателей в порядке A, B и C, они получат уведомления
в порядке C, B, A.
Теоретически это не должно иметь значения. Прин-
цип хорошей организации наблюдателей заключает-
ся в том, что два наблюдателя, отслеживающих один
и тот же субъект, не должны иметь никаких зависимо-
стей друг к другу относительно порядка. Если же порядок
важен
, значит, у двух наблюдателей есть некоторые тон-
кие связи, способные в итоге сыграть с вами злую шутку.
Do'stlaringiz bilan baham: |