говорить еще раз, как дизайн зависит от самого вопроса.
из вещей, над которой я сейчас работаю, имеет некоторые сходства с игрой. В целях иллюстрации я собираюсь объяснить свою проблему на примере, взятом из вымышленной, гипотетической игры.
Давайте назовем этоСмертельный бластер 4: Смерть, В DB4 у вас есть рядShip
объекты, которые периодически и случайно встречаютсяPhenomena
как они путешествуют. ДанныйPhenomenon
может иметь ноль, один или болееEffects
наShip
что сталкивается с этим. Например, у нас может быть четыре видаShips
и три видаPhenomena
.
Phenomena ========================================== Ships GravityWell BlackHole NebulaField ------------ ------------------------------------------ RedShip +20% speed -50% power -50% shield BlueShip no effect invulnerable death Effects of Various GreenShip -20% speed death +50% shield Phenomena on Ships YellowShip death +50% power no effect
Дополнительно,Effects
могут взаимодействовать друг с другом. Например,GreenShip
это как вGravityWell
иNebulaField
может получить некоторую синергию между сгенерированнымSpeedEffect
а такжеShieldEffect
, В таких случаях синергетический эффект сам по себе являетсяEffect
- например, может бытьPowerLevelSynergyEffect
что является результатом этого взаимодействия. Нет информации, кроме набораEffects
действуя наShip
необходимо решить, каким должен быть конечный результат.
Вы можете начать видеть проблему, возникающую здесь. В качестве наивного первого подхода,либо каждыйShip
придется знать, как справиться с каждымPhenomenon
или каждыйPhenomenon
придется знать о каждомShip
, Это явно неприемлемо, поэтому мы хотели бы перенести эти обязанности в другое место. Очевидно, здесь есть хотя бы один внешний класс, возможно,Mediator
или жеVisitor
какой-то
Но какой лучший способ сделать это? Идеальное решение, вероятно, будет иметь следующие свойства:
Так же легко добавить новыйShip
как это добавить новыйPhenomenon
.Взаимодействия, которые не дают никакого эффекта, являются стандартными и не требуют дополнительного кода для представления. Соглашение по конфигурации.Понимает какEffects
взаимодействовать друг с другом и способен управлять этими взаимодействиями, чтобы решить, каким будет конечный результат.Думаю, я уже решил, каким будет мой подход, но мне интересно услышать, что такое лучший дизайн консенсуса. С чего бы начать? Какие пути вы бы исследовали?
Последующее обновление: Спасибо всем за ответы. Вот что я в итоге делаю. Моим главным наблюдением было то, что число различныхEffects
кажется небольшим по сравнению с количеством возможныхPhenomena
× Ships
взаимодействия. То есть, хотя есть много возможныхкомбинации взаимодействий, количествовиды результатов из этих взаимодействий меньшее число.
Вы можете видеть, что, например, хотя в таблице 12 комбинаций взаимодействий, есть только пятьвиды эффектов: модификации скорости, модификации силы, модификации щита, неуязвимость, смерть.
Я ввел третий класс,InteractionResolver
, чтобы определить результат взаимодействия. Он содержит словарь, который отображаетShip-Phenomenon
пары кEffects
(которые являются в основном делегатом, который выполняет эффект и некоторые метаданные). каждыйShip
вручаетсяEffectStack
соответствуетEffects
он испытывает, когда результат вычислений взаимодействие завершено.
Ships
затем используйтеEffectStack
определить фактический результатEffects
на них, добавив модификаторы к их существующим атрибутам и свойствам.
Мне это нравится, потому что:
Корабли никогда не должны знать о явлениях.Сложность отношения «Корабль-Явления» абстрагируется в InteractionResolver.Детали того, как разрешить множественные и, возможно, сложные эффекты, абстрагируютсяInteractionResolver
, Корабли должны применять эффекты только по мере необходимости.Это позволяет дополнительные полезные рефакторинги. Например,путь в котором эффекты процессов на судне могут быть дифференцированы путемEffectProcessorStrategy
, По умолчанию могут обрабатываться все эффекты, но, скажем,BossShip
может игнорировать незначительные эффекты, имея другойEffectProcessorStrategy
.