Game Programming Patterns / Паттерны программирования в играх: 1.3. Observer
| Английский оригинал | Перевод на русский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
class Subject kamillxiii 01.05.14 в 11:15 |
|
|
{ kamillxiii 01.05.14 в 11:15 |
||
|
private: kamillxiii 01.05.14 в 11:15 |
||
|
Observer* observers_[MAX_OBSERVERS]; kamillxiii 01.05.14 в 11:15 |
||
|
int numObservers_; kamillxiii 01.05.14 в 11:15 |
||
|
}; kamillxiii 01.05.14 в 11:15 |
||
|
В реальном коде вам лучше использовать динамическую коллекцию вместо простого массива. kamillxiii 01.05.14 в 11:17 В реальном коде используется динамически расширяемая коллекция вместо простого массива. IngaJolly 17.06.14 в 18:23 |
||
|
Я описываю основы для тех людей, что пришли из других языков и не знают стандартную библиотеку C++. kamillxiii 01.05.14 в 11:19 Здесь я придерживаюсь основ ради людей, пришедших из других языков программирования, не знающих стандартной библиотеки C++. IngaJolly 17.06.14 в 18:24 |
||
|
Важным моментом является то, что субъект предоставляет публичное API для изменения этого списка. kamillxiii 01.05.14 в 11:19 Важный момент: субъект предоставляет публичный API для изменения списка: IngaJolly 17.06.14 в 18:25 |
||
|
class Subject kamillxiii 01.05.14 в 11:15 |
||
|
{ kamillxiii 01.05.14 в 11:15 |
||
|
public: kamillxiii 01.05.14 в 11:15 |
||
|
void addObserver(Observer* observer) kamillxiii 01.05.14 в 11:15 |
||
|
{ kamillxiii 01.05.14 в 11:15 |
||
|
// Добавить в список... kamillxiii 01.05.14 в 11:20 // Добавить в массив... IngaJolly 17.06.14 в 18:26 |
||
|
} kamillxiii 01.05.14 в 11:15 |
||
|
void removeObserver(Observer* observer) kamillxiii 01.05.14 в 11:15 |
||
|
{ kamillxiii 01.05.14 в 11:15 |
||
|
// Удалить из списка... kamillxiii 01.05.14 в 11:21 // Удалить из массива... IngaJolly 17.06.14 в 18:26 |
||
|
} kamillxiii 01.05.14 в 11:15 |
||
|
// Все остальное... kamillxiii 01.05.14 в 11:22 // Остальные данные... IngaJolly 17.06.14 в 18:27 |
||
|
}; kamillxiii 01.05.14 в 11:15 |
||
|
Это позволяет контролировать, кто получает сообщения, вне этого кода. kamillxiii 01.05.14 в 11:23 Теперь внешний код контролирует, кто получает уведомления. IngaJolly 17.06.14 в 18:27 |
||
|
Субъект общается с наблюдателями, но не связан с ними. kamillxiii 01.05.14 в 11:23 |
||
|
В нашем примере ни одна строчка физического кода не говорит о наличии достижений. kamillxiii 01.05.14 в 11:25 В нашем примере в физическом коде не будет ни слова про достижения. IngaJolly 17.06.14 в 18:28 |
||
|
Тем не менее, он все еще оповещает систему достижений. kamillxiii 01.05.14 в 11:25 Тем не менее, уведомления все еще могут приходить системе достижений. IngaJolly 17.06.14 в 18:29 |
||
|
Это очень умно со стороны шаблона. kamillxiii 01.05.14 в 11:27 В этом хитрость данного паттерна. IngaJolly 17.06.14 в 18:29 |
||
|
Также важно, что субъект имеет список наблюдателей вместо одного-единственного. kamillxiii 01.05.14 в 11:27 Также важно, что у субъекта есть не один, а несколько наблюдателей. IngaJolly 27.08.14 в 18:18 |
||
|
Это говорит нам о том, что наблюдатели завязаны явно друг на друга. kamillxiii 01.05.14 в 11:29 Это позволяет избежать ситуации, когда наблюдатели неявно связаны друг с другом. IngaJolly 28.08.14 в 16:50 |
||
|
К примеру, аудио движок также слушает событие падения, чтобы проиграть соответствующий звук. kamillxiii 01.05.14 в 11:32 Скажем, звуковой движок также ждет падения, чтобы проиграть соответствующий звук. IngaJolly 28.08.14 в 16:56 |
||
|
Если бы субъект поддерживал только одного наблюдателя, то аудио движок заменил бы систему достижений. kamillxiii 01.05.14 в 11:36 Если бы субъект поддерживал только одного наблюдателя, при регистрации звукового движка отменялась бы регистрация системы достижений. IngaJolly 28.08.14 в 16:57 |
||
|
Это означало, что эти две системы пересекаются между собой - и это очень неприятный момент, когда одна из них фактически отключает другую. kamillxiii 01.05.14 в 11:37 Это значит, что две системы вмешивались бы в работу друг друга самым неприятным образом, ибо одна отключала бы другую. IngaJolly 28.08.14 в 18:54 |
||
|
Поддержка списка наблюдателей гарантирует, что каждый наблюдатель обрабатывается независимо от других. kamillxiii 03.05.14 в 03:07 Поддержка списка наблюдателей гарантирует независимость каждого из них от других. IngaJolly 29.08.14 в 10:03 |
||
|
Каждый из них думает, что он единственный в мире следит за субъектом. kamillxiii 03.05.14 в 03:09 Каждый думает, что он один следит за субъектом. IngaJolly 29.08.14 в 10:12 |
||
|
Другой задачей субъекта является отправка оповещений: kamillxiii 03.05.14 в 03:22 Другая задача субъекта - это отправка уведомлений: IngaJolly 29.08.14 в 10:18 |
||
|
class Subject kamillxiii 01.05.14 в 11:15 |
||
|
{ kamillxiii 01.05.14 в 11:15 |
||
|
protected: kamillxiii 01.05.14 в 11:15 |
||
|
void notify(const Entity& entity, Event event) kamillxiii 01.05.14 в 11:15 |
||
|
{ kamillxiii 01.05.14 в 11:15 |
||
|
for (int i = 0; i < numObservers_; i++) kamillxiii 01.05.14 в 11:15 |
||
|
{ kamillxiii 01.05.14 в 11:15 |
||
|
observers_[i]->onNotify(entity, event) kamillxiii 01.05.14 в 11:16 |
||
|
; kamillxiii 01.05.14 в 11:16 |
||
|
} kamillxiii 01.05.14 в 11:16 |
||
|
} kamillxiii 01.05.14 в 11:16 |
||
|
// Все остальное... kamillxiii 03.05.14 в 03:23 // Остальные данные... IngaJolly 29.08.14 в 10:26 |
||
|
}; kamillxiii 01.05.14 в 11:16 |
||
|
Заметьте, этот код предполагает, что наблюдатели не будут менять список в процессе вызова onNotify(). kamillxiii 03.05.14 в 03:25 Отметим, что наблюдатели не должны изменять список в методах onNotify. IngaJolly 29.08.14 в 16:33 |
||
|
Более надежным решением будет запрещать или изящно обрабатывать изменения такого рода. kamillxiii 03.05.14 в 03:27 Более надежное решение - предотвращать или изящно обрабатывать одновременные изменения. IngaJolly 29.08.14 в 17:01 |
