【发布时间】:2011-02-09 06:30:10
【问题描述】:
我正在开发一个用 Java 编写的小游戏(但问题与语言无关)。因为我想探索各种设计模式,所以我挂断了 Composite pattern/Entity 系统(我最初读到的是 here 和 here)作为典型深层层次继承的替代方案。
现在,写了几千行代码后,我有点困惑。我认为理解这种模式并且我喜欢使用它。我认为这很酷,而且像星巴克一样,但感觉它提供的好处有点短暂,而且(最让我烦恼的是)很大程度上取决于你的粒度。
这是上面第二篇文章的图片:
我喜欢对象(游戏实体,或任何您想称呼它们的名称)具有最少组件集的方式,并且推断的想法是您可以编写如下代码:
BaseEntity Alien = new BaseEntity();
BaseEntity Player = new BaseEntity();
Alien.addComponent(new Position(), new Movement(), new Render(), new Script(), new Target());
Player.addComponent(new Position(), new Movement(), new Render(), new Script(), new Physics());
.. 这真的很好...但在现实中,代码最终看起来像
BaseEntity Alien = new BaseEntity();
BaseEntity Player = new BaseEntity();
Alien.addComponent(new Position(), new AlienAIMovement(), new RenderAlien(), new ScriptAlien(), new Target());
Player.addComponent(new Position(), new KeyboardInputMovement(), new RenderPlayer(), new ScriptPlayer(), new PhysicsPlayer());
似乎我最终拥有了一些由较小组件组成的非常专业的组件。很多时候,我必须制作一些具有其他组件依赖关系的组件。毕竟,没有位置怎么渲染?不仅如此,最终渲染玩家与外星人与手榴弹的方式也可能完全不同。除非你制作一个非常大的组件(在这种情况下......你为什么要使用复合模式?)
再举一个现实生活中的例子。我的游戏中有可以装备各种装备的角色。当装备一件装备时,一些统计数据以及视觉显示的内容都会发生变化。这是我的代码现在的样子:
billy.addControllers(new Movement(), new Position(), new CharacterAnimationRender(), new KeyboardCharacterInput());
billy.get(CharacterAnimationRender.class).setBody(BODY.NORMAL_BODY);
billy.get(CharacterAnimationRender.class).setFace(FACE.BLUSH_FACE);
billy.get(CharacterAnimationRender.class).setHair(HAIR.RED_HAIR);
billy.get(CharacterAnimationRender.class).setDress(DRESS.DRAGON_PLATE_ARMOR);
以上CharacterAnimationRender.class 只会影响视觉上显示的内容。所以我显然需要制作另一个处理装备统计信息的组件。但是,我为什么要这样做:
billy.addControllers(new CharacterStatistics());
billy.get(CharacterAnimationRender.class).setBody(BODY.NORMAL_BODY);
billy.get(CharacterStatistics.class).setBodyStats(BODY_STATS.NORMAL_BODY);
什么时候我可以制作一个CharacterGearStuff 控制器/组件来处理统计数据的分布和视觉变化?
底线,我不确定这应该如何提高生产力,因为除非您想手动处理所有事情,否则您仍然必须创建依赖于 2 个以上组件的“元组件”(并修改/交叉修改它们的所有子组件——让我们回到 OOP)。或者,也许我在想它是完全错误的。我是吗?
【问题讨论】:
标签: java design-patterns language-agnostic composite