У меня следующая проблема.
Предмет может иметь много состояний:
NORMAL = 0000000
DRY = 0000001
HOT = 0000010
BURNING = 0000100
WET = 0001000
COLD = 0010000
FROZEN = 0100000
POISONED= 1000000
Элемент может иметь несколько состояний одновременно, но не все из них
- Невозможно быть сухим и мокрым одновременно.
- Если вы ХОЛОДНО промоклите предмет, он превращается в ЗАМОРОЖЕННЫЙ.
- Если вы ГОРЯЧЕЕ ВЛАЖНОЕ изделие, оно превращается в нормальный
- Предмет может быть ГОРЯЩИМ и ЯДНЫМ
И т.п.
Я попытался установить бинарные флаги для состояний и использовать AND для объединения различных состояний, прежде чем проверять, возможно ли это или нет, или переходить в другой статус.
Существует ли конкретный подход для эффективного решения этой проблемы без использования бесконечного переключателя, который проверяет каждое состояние с каждым новым состоянием?
Относительно легко проверить 2 разных состояния, но если существует третье состояние, это не тривиально.
c++
rpg
design-patterns
binary
vgonisanz
источник
источник
Ответы:
Когда мне нужно использовать флаги, я обычно делаю что-то подобное.
Это делает их использование для таких вещей, как apply_cold (), очень простым, и вы, очевидно, можете создавать условия в вашем состоянии, такие как dry и wet.
источник
Два наблюдения:
COLD
иHOT
переходы в том, как вы их упоминаете, а не состояния.Объединение этих наблюдений приведет к чему-то вроде этого:
источник
Представляя ваши состояния в виде битовой маски, как вы пишете, вы можете просто перевести ваши описания ограничений в код:
Вы можете заключить это в объект,
makeStateConsistent()
который вы можете вызвать перед проверкой битов состояния, чтобы убедиться, что состояние имеет смысл.Однако одним из ограничений этого подхода является то, что он не может учитывать порядок изменений состояния. Например, если вы хотите получить другой результат для горячих предметов, которые становятся мокрыми, чем для мокрых предметов, которые становятся горячими, вы не можете сделать это следующим образом: все, что
makeStateConsistent()
видит метод - это горячий и мокрый объект, без информации о том, как так и должно быть.Вместо того , что вы могли бы сделать , это государство пункт частным (по крайней мере , концептуально) и управлять ею с помощью набора методов , таких как
coolItem()
,heatItem()
,wetItem()
,dryItem()
и так далее. Таким образом, сами методы изменения состояния могут позаботиться о любых дополнительных изменениях. Например,heatItem()
метод может выглядеть примерно так:Конечно, вы все еще можете иметь
makeStateConsistent()
метод в качестве резервной копии, на случай, если у вас есть ошибка в ваших методах изменения состояния.Кроме того, в некоторых случаях вы можете упростить код за счет устранения ненужных состояний. Например, вам действительно нужно отдельное
FROZEN
состояние, или этого будет достаточно, чтобы относиться к холодным и влажным предметам как к замороженным?источник