对象管理器?设计模式

7
我有很多对象需要传递给其他对象。这是一个游戏,所以玩家需要了解世界,世界需要了解地图等等。
为了避免把所有这些东西都传来传去,我考虑创建一个“主”对象管理器,然后在其中注册这些对象。我将传递主对象管理器,需要使用某些内容的所有对象只需执行“masterObject.getPlayer()”或其他操作。
这是否是一种真正的设计模式?如果是,它被称为什么?有没有缺点。
4个回答

16

这是一种常用的方法,如果处理得当可以非常有用。虽然有些人不喜欢它们,并把它们称为“上帝类”,但如果结构合理,它们并不是。问题出现在你只是想把它看作“包含所有内容的类”时 - 但如果你考虑信息结构,你应该没问题。

让我们举个例子。假设你感兴趣的类叫做“游戏”。这总是一个很好的开始,因为它代表了真实的世界实体。游戏应该知道关于自己的事情:player1,player2,map,turnNumber。在Game中添加方法来访问这些信息,这是完全正确和良好的设计。然后这些对象将依次了解自己的情况。玩家将知道姓名、技能水平和剩余能量。地图将知道大小,以及每个方格上的地形情况。如果您需要了解单个方格的信息,则让Map类实现getSquare(x,y)即可。方块知道它的地形类型。

关键是你只给方法传递它需要的东西。计算两个单位之间路径的方法将采用Map作为其参数。你不会把整个Game类传递进去让它提取Map。

许多系统都有这样的对象。java.lang.Runtime就是一个例子。但是你应该通过上述技术尽量减少它们的使用。

有一个非常重要的诱惑需要避免。当你发现你的“主”类几乎被传递给每个方法时,你可能会想:“为什么不让每个方法都可以访问这个类而不用它作为参数?”那样就会陷入单例模式。避免。


我的脚本引擎怎么样?我有一些在特定事件期间触发的脚本。比如玩家受到攻击时,会触发一个“onDamage.js”脚本。该脚本需要访问玩家(或者至少能够调用player.giveDamage()),并且需要了解地图(如果是游侠,外面受到的伤害更少),还需要了解进行攻击的敌人(或者至少enemy.getDamageModifiers())。此外,该脚本还将获取图像效果(或者至少effectsEngine.displayEffect()),并且需要更新HUD等。但是该脚本包含在玩家对象中。你会如何设计这个? - user697111
那是另一个问题,我建议你单独提问。 - DJClayworth
希望你能加入一段关于解决依赖关系的内容。比如说,我有一个需要来自类B的东西的类A或者两个类相互依赖。这在引导时非常困难,特别是在涉及多线程的情况下。面向对象设计模式建议针对这种情况采用什么样的稳定基础?例如,你脑海中闪现过哪些模式名称? - Manuel Arwed Schmidt

3
你所描述的是一种设计模式,或者说是一种反模式。它有时被称为上帝类,应该避免使用。 维基百科的文章解释了上帝类的基本问题。具体而言,这样一个对象将违反德米特法则。它基本上是在说不要和陌生人交谈。从上帝对象检索到的所有对象都是陌生人,最好避免发送消息/调用方法。

谢谢提供链接。这里不会提供方法,只有对象。它更像是一个通用工厂,提供游戏对象或更像是一个通信“中心”,允许对象相互传递。 - user697111
一个对象中包含多个子对象,它们需要相互交互,有什么好的设计模式吗?我考虑使用某种通信渠道,但不确定哪种最适合。 - user697111
我认为DJClayworth的解释非常好。特别是“关键是…”这一段。 - willscripted

1

从另一个角度来看,与 Will O 和 Jeune 的答案相比,这只是一份好的旧记录;既不多也不少。是否这是正确的设计决策或者是“上帝类”反模式的实例取决于具体情况。我认为,当这个类不会使您的整个代码库相互递归,并且当该类中几乎没有实际代码时,仅有实例属性引用所有其他对象时,它就是可以接受的。


0

尝试看一下观察者模式。它类似于您所描述的世界。有一个主对象(可观察对象),还有注册自己到主对象的观察者。如果世界发生变化,主对象只需通知观察者。

此外,我想您可以添加其他方法以适应您的需求,但这基本上就是概念。


我更多地考虑了一下地图,可以使用“masterObject.getPlayer()”来获取玩家,而玩家可以使用“masterObject.getMap()”来获取地图。 - user697111

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接