什么是解决相互作用的组合爆炸的最佳方法?

Joh*_*lla 10 c# design-patterns software-design

我现在正在做的事情之一与游戏有一些相似之处.出于说明的目的,我将使用从虚构的假设游戏中抽取的示例来解释我的问题.

我们称之为DeathBlaster 4:The Deathening.在DB4中,您有许多Ship对象Phenomena在旅行时会定期和随机地遇到.一个给定的Phenomenon可能EffectsShip遇到它时有零个,一个或多个.例如,我们可能有四种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可导出某种所生成之间的协同作用的SpeedEffectShieldEffect.在这种情况下,协同效应本身就是Effect- 例如,可能存在PowerLevelSynergyEffect这种相互作用的结果.除了Effects在a 上采取行动之外,不需要任何其他信息Ship来解决最终结果应该是什么.

你可能会开始看到这里出现的问题.作为一种天真的第一种方法,要么每个Ship人都必须知道如何处理每一个Phenomenon,或者每个Phenomenon人都必须知道每一个Ship.这显然是不可接受的,所以我们希望将这些责任转移到其他地方.显然,这里至少有一个外部类,可能是某种MediatorVisitor某种类型.

但是最好的方法是什么?理想的解决方案可能具有以下特性:

  • 就像添加一个新的一样容易Ship添加新的Phenomenon.
  • 不产生影响的交互是默认的,不需要额外的代码来表示.约定优于配置.
  • 了解Effects彼此之间的交互方式,并能够管理这些交互,以决定最终结果.

我想,我已经决定了我的方法,但我很想知道最佳设计共识是什么.你会从哪里开始的?你会探索什么途径?



后续更新:感谢大家的回复.这就是我最后做的事情.我的主要观察结果是,Effects相对于可能的Phenomena× Ships相互作用的数量,不同的数量似乎很小.也就是说,尽管存在许多可能的交互组合,但这些交互的结果种类数量较少.

你可以看到,例如,虽然在表12名相互作用的组合,只有5 种类的效果:修改速度,修改权力,修改屏蔽,刀枪不入,死亡.

我介绍了第三类,InteractionResolver以确定交互的结果.它包含一个将对映射Ship-Phenomenon到的字典Effects(基本上是执行效果的委托和一些元数据).当计算交互的结果完成时,每个Ship交给EffectStack对应于Effects它的体验.

Ships然后使用它EffectStack来确定它们的实际结果Effects,方法是将修饰符添加到它们的现有属性和属性中.

我喜欢这个,因为:

  1. 船舶永远不需要了解现象.
    • Ship-Phenomena关系的复杂性被抽象到InteractionResolver中.
    • 如何解决多个和可能复杂的效果的细节被抽象了Ship.船只必须根据需要应用效果.
    • 这可以实现额外的有用重构.例如,该方式中,船舶处理效果可以通过使被区分Phenomena.默认可能是处理所有效果,但是,例如,a Ship可能会通过使用不同的效果忽略次要效果Phenomena.

Ree*_*sey 1

一个有趣的潜在选择是使用访问者模式的变体。

Judith Bishop 和 R. Nigel Horspool 撰写了一篇关于设计模式效率的论文,其中他们解释了使用 C# 3 功能的经典访问者模式的各种变体。

特别是,我会看看他们如何与代表一起处理访问者模式。使用委托列表或堆栈可能会为您提供一种有趣的方式来处理来自多个对象的多种效果,并且更容易扩展类层次结构的任一侧(添加船舶或添加效果),而无需进行大量破坏性代码更改。