Game Programming Patterns / Паттерны программирования в играх: 1.3. Observer

← →
Английский оригинал Перевод на русский

Сожалеем, но текст оригинала доступен только зарегистрированным пользователям.

Будь это реальным кодом, я бы сделал так.

kamillxiii 03.05.14 в 14:29

0

В реальном коде я бы сделал так.

IngaJolly 31.08.14 в 19:16

0

Всё, что осталось, это отправить оповещение.

kamillxiii 03.05.14 в 14:29

0

Осталось только отправить уведомление.

IngaJolly 31.08.14 в 19:16

0

Это не сложнее, чем простой обход списка.

kamillxiii 03.05.14 в 14:30

0

Это так же просто, как обход списка:

IngaJolly 31.08.14 в 19:16

0

void Subject::notify(const Entity& entity, Event event)

kamillxiii 03.05.14 в 14:30

1

{

kamillxiii 03.05.14 в 14:30

1

Observer* observer = head_;

kamillxiii 03.05.14 в 14:30

1

while (observer != NULL)

kamillxiii 03.05.14 в 14:30

1

{

kamillxiii 03.05.14 в 14:30

1

observer->onNotify(entity, event)

kamillxiii 03.05.14 в 14:30

1

;

kamillxiii 03.05.14 в 14:30

1

observer = observer->next_;

kamillxiii 03.05.14 в 14:30

1

}

kamillxiii 03.05.14 в 14:30

1

}

kamillxiii 03.05.14 в 14:30

1

Тут мы обходи весь список и оповещаем каждого наблюдателя.

kamillxiii 05.05.14 в 11:06

0

Обходим весь список и уведомляем каждого наблюдателя из него.

IngaJolly 31.08.14 в 19:17

0

Благодаря этому, наблюдатели имеют равный приоритет, а также независимость друг от друга.

kSky7000 06.05.14 в 05:14

0

Теперь все наблюдатели имеют одинаковый приоритет и независимы друг от друга.

IngaJolly 31.08.14 в 19:18

0

Можно немного модифицировать этот код. Например при получении наблюдателем оповещения, он возвратит флаг, показывающий, нужно ли продолжать движение по списку или остановиться.

kSky7000 06.05.14 в 10:24

0

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

IngaJolly 31.08.14 в 19:19

0

Если сделаете это, считайте что вплотную приблизились к паттерну Chain of Responsibility.

kSky7000 06.05.14 в 10:33

0

Сделав это, максимально приблизимся к паттерну "Цепочка обязанностей" (Chain of Responsibility).

IngaJolly 31.08.14 в 19:21

0

Неплохо, не так ли?

kSky7000 06.05.14 в 10:34

0

Неплохо, правда?

IngaJolly 31.08.14 в 19:21

0

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

kSky7000 06.05.14 в 10:37

0

Субъект может иметь неограниченное количество наблюдателей без намека на динамическую память.

IngaJolly 31.08.14 в 19:22

0

И теперь это работает также быстро, как это было с простым массивом.

kSky7000 06.05.14 в 10:47

0

А изменение списка производится так же быстро, как и у обычного массива.

kamillxiii 06.05.14 в 13:57

0

Регистрация и прекращение регистрации происходят так же быстро, как и в случае с простым массивом.

IngaJolly 31.08.14 в 19:24

0

Однако, ради этого мы пожертвовали небольшой особенностью.

kSky7000 06.05.14 в 10:50

0

Хотя мы пожертвовали небольшой возможностью.

IngaJolly 31.08.14 в 19:25

0

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

kSky7000 06.05.14 в 11:09

0

Объект наблюдателя в качестве узла списка может находиться только в одном списке субъекта.

IngaJolly 31.08.14 в 19:27

0

Другими словами, наблюдатель может следить только за одним субъектом.

kSky7000 06.05.14 в 11:12

0

Другими словами, наблюдатель может следить только за одним субъектом в данный промежуток времени.

IngaJolly 31.08.14 в 19:28

0

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

kSky7000 06.05.14 в 11:18

1

Вас вполне могут не волновать подобные ограничения.

kSky7000 06.05.14 в 11:21

0

Можно жить и с этим ограничением.

IngaJolly 01.09.14 в 16:24

0

Я думаю, чаще всего субъект имеет нескольких наблюдателей, чем наоборот.

kSky7000 06.05.14 в 11:31

0

Естественнее для субъекта иметь нескольких наблюдателей, чем наоборот.

IngaJolly 01.09.14 в 16:25

0

Но если вас это интересует, есть одно более комплексное решение, все еще не требующее динамической работы с памятью.

kSky7000 06.05.14 в 11:32

0

Но если это является проблемой, есть другое, более сложное решение, также не требующее динамического выделения.

IngaJolly 01.09.14 в 16:25

0

Не думаю что смогу уместить его в эту главу, но я сделаю набросок и думаю вы все поймете.

kSky7000 06.05.14 в 11:36

0

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

IngaJolly 01.09.14 в 16:27

0

Пул узлов списка.

kSky7000 06.05.14 в 11:36

0

Пул узлов списка

IngaJolly 01.09.14 в 16:27

0

Как и раньше, каждый субъект имеет связный список наблюдателей.

kSky7000 06.05.14 в 11:37

0

Как прежде, каждый субъект имеет связанный список наблюдателей.

IngaJolly 01.09.14 в 16:27

0

Тем не менее, эти узлы списка не будут объектами наблюдателя сами.

kSky7000 06.05.14 в 11:45

0

Однако узлы этого списка не являются объектами наблюдателя.

IngaJolly 01.09.14 в 16:28

0

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

kSky7000 06.05.14 в 11:51

0

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

IngaJolly 01.09.14 в 16:30

0

Потому как на одного наблюдателя может указывать множество узлов, этот наблюдатель может следить более чем за одним субъектом.

kamillxiii 06.05.14 в 14:00

0

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

IngaJolly 01.09.14 в 16:31

0

Мы вернули возможность наблюдать несколькими субъектами за раз.

kamillxiii 06.05.14 в 14:01

0

Теперь можно снова наблюдать за несколькими субъектами одновременно.

IngaJolly 01.09.14 в 16:59

0

Связанные списки бывают двух видов.

kamillxiii 06.05.14 в 14:02

1

В первом, который вам известен со школы, есть узел, в котором хранятся данные.

kamillxiii 06.05.14 в 14:03

0

В первом, который проходят в школе, есть узловой объект, содержащий данные.

IngaJolly 01.09.14 в 17:20

0

В предыдущем примере с наблюдателем все было наоборот: данные (в данном случае, сам наблюдатель) содержат ссылку на узел (например, next_pointer).

kamillxiii 06.05.14 в 14:07

0

В предыдущем примере со связанным наблюдателем было наоборот: данные (в данном случае, наблюдатель)

IngaJolly 01.09.14 в 17:22

0

-

kamillxiii 06.05.14 в 14:08

0

содержали узел (то

IngaJolly 01.09.14 в 17:22

0

-

kamillxiii 06.05.14 в 14:08

0

есть,

IngaJolly 01.09.14 в 17:22

0

-

kamillxiii 06.05.14 в 14:08

0

указатель next_).

IngaJolly 01.09.14 в 17:22

0

Последний вариант называется "навязчивым" ("intrusive") списком, поскольку использование объекта в списке "навязывает" ему тип этого объекта.

kamillxiii 06.05.14 в 14:12

0

Второй вид связанного списка называется "интрузивным", потому что использование объекта в списке вторгается в его определение.

IngaJolly 01.09.14 в 17:31

0
+1

Это делает такие списки менее гибкими, но, как мы видели, более эффективными.

kamillxiii 06.05.14 в 14:13

0

Интрузивные списки менее гибкие, но, как мы видели, более эффективные.

IngaJolly 01.09.14 в 17:41

0

Они распространены в таких местах, как ядро Linux, где этот компромисс сильно ощутим.

kamillxiii 06.05.14 в 14:14

0

Они распространены в таких местах, как ядро Linux, где этот компромисс имеет смысл.

IngaJolly 01.09.14 в 17:43

0

Способ избежания динамического создания прост: так как все узлы одного типа и размера, вы заранее создаёте Пул Объектов (Object Pool) для них.

kamillxiii 06.05.14 в 14:16

0

Избежать динамического выделения просто: так как все узлы имеют одинаковый размер и тип, можно заранее выделить место под "Объектный пул" (Object Pool) из них.

IngaJolly 01.09.14 в 17:46

0
+1

Это дает вам фиксированное количество узлов списка, и по мере надобности вы можете снова и снова использовать их не производя реального выделения памяти.

kamillxiii 06.05.14 в 14:24

0

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

IngaJolly 01.09.14 в 17:58

0

Оставшиеся Проблемы

kamillxiii 06.05.14 в 14:25

0

Оставшиеся проблемы

IngaJolly 01.09.14 в 17:59

0

Я думаю, мы прогнали из этого паттерна те две страшилки, которые пугали людей.

kamillxiii 06.05.14 в 14:30

0

Думаю, мы прогнали двух главных монстров, пугающих людей в данном паттерне.

IngaJolly 01.09.14 в 18:34

0

И как мы видим, паттерн прост, быстр и может легко подстраиваться под стиль управления памятью.

kamillxiii 06.05.14 в 14:33

0

Как видно, паттерн простой, быстрый, его можно настроить для прекрасной работы с управлением памятью.

IngaJolly 01.09.14 в 18:42

0

Но значит ли это, что вы постоянно должны использовать наблюдателей?

kamillxiii 06.05.14 в 14:36

0

Но значит ли это, что нужно использовать наблюдателей все время?

IngaJolly 01.09.14 в 18:43

0

Это уже другой вопрос.

kamillxiii 06.05.14 в 14:37

1
Минутку...

← Предыдущая страница

Следующая страница →