Я думаю, что Шаблон наблюдателя может быть адаптирован.
Идея заключается в том, что каждый Node
поддерживает предварительно вычисленный список и просто уведомляется своим родителем о любом обновлении, чтобы он мог пересчитать этот список.
Это можно сделать двумя разными способами:
- уведомить, что произошло изменение, но ничего не пересчитывать
- пересчитывать при каждом обновлении
Я бы посоветовал перейти с 1
, если это возможно, так как он не требует пересчета всего мира при обновлении root, а только пересчета при необходимости (фактически, lazy eval), но вы можете предпочесть второй вариант, если вы обновляете редко но нужно использовать быстрый быстрый поиск (хотя есть и другие проблемы с параллелизмом).
Давайте проиллюстрируем Решение 1:
Root ___ Node1 ___ Node1A
\ \__ Node1B
\_ Node2 ___ Node2A
\__ Node2B
Теперь, для начала, никто из них ничего не вычислил заранее (все находятся в грязном состоянии), если я попрошу правила Node2A
:
Node2A
понимает, что это грязно: он запрашивает Node2
правила
Node2
понимает, что это грязно: он запрашивает Root
Root
не имеет родителя, поэтому он не может быть грязным, он отправляет свои правила на Node2
Node2
кэширует ответ от Root
, объединяет свои правила с правилами, полученными от Root
и очищает грязный бит, отправляет результат слияния (кэшированный сейчас) в Node2A
Node2A
кэширует, объединяет, очищает грязный бит и возвращает результат
Если я впоследствии запрашиваю Node2B
правил:
Node2B
грязно, он запрашивает Node2
Node2
чисто, отвечает
Node2B
кэширует, объединяет, очищает грязный бит и возвращает результат
Обратите внимание, что Node2
ничего не пересчитал.
В случае обновления:
- Я обновляю
Node1
: я использую кэшированные правила Root
для пересчета новых правил и отправляю такты Node1A
и Node1B
, чтобы уведомить их, что их кеш устарел
Node1A
и Node1B
установили свой грязный бит, они также распространили бы это уведомление, если бы у них были дети
Обратите внимание, что из-за того, что я кэшировал правила Root
, мне не нужно запрашивать объект Root
, если это достаточно простая операция, вы можете вообще не кэшировать их: если вы не играете, распространяемый здесь и запрос Root
включает только обход памяти, вы можете предпочесть не дублировать его, чтобы сэкономить память и вести бухгалтерский учет.
Надеется, что это поможет вам.