用于构建大型对象层次结构的模式

时间:2010-01-25 14:38:09

标签: design-patterns oop architecture

我遇到一个涉及相对较大的对象层次结构的问题,如下所示:

  • 游戏有一个社区管理员
  • 社区经理有一个网络
  • network 有很多玩家
  • network 有很多友谊
  • 播放器有一个策略管理器
  • 播放器有一个内存
  • 播放器有一个邻居
  • 邻居有很多玩家
  • 策略经理有很多策略

正如您所看到的,层次结构相对复杂,并且至少在一个地方是循环的(网络中有许多代理具有一个具有一个网络的邻域)。目前我在GameFactory类上使用静态构造方法构建整个层次结构,但我很确定这是最不灵活的方法!

在构建复杂的对象层次结构方面,最好使用哪种模式?我已经阅读了Factory MethodAbstract FactoryBuilder模式,我认为其中一种工厂模式是合适的,但我真的不知道如何将它应用于这样一个复杂的模式层次?

正如我所看到的,系统的每个部分都需要很多工厂,但这会产生一组镜像模型类的工厂类。


编辑:从目前为止给出的建议讨论中可以清楚地看到,我应该更多地解释为什么我要求工厂构建我的对象层次结构而不是允许构造函数自己构建它们的依赖关系。

这是因为我使用依赖注入来帮助测试驱动开发。我正在对测试采用mockist方法,这需要能够注入表示对象依赖关系的模拟,因此我必须避免在任何构造函数中使用new

根据目前给出的建议,似乎有很多可能的方法:

  • 在每个类中创建一个辅助构造函数,用于构建正在构造的对象所需的任何依赖项。这允许依赖注入和简单的对象层次结构构建。
  • 有一个工厂类(根据所使用的工厂模式的类型,可以是单个工厂类或它们的层次结构)映射到每个域类来处理它的构造。
  • 使用这些方法的组合,其中工厂类仅在构造过程中存在变化时创建(即,在某些情况下需要构建不同的子类)

我倾向于选择最后一条路线。在这种情况下采取最佳方法的共识是什么?


编辑:我正在撤销当前的答案(Patrick Karcher的答案),因为现在该问题的重点已经澄清,所有建议都不是完整答案。

3 个答案:

答案 0 :(得分:4)

了解为什么确切地说你需要一个工厂是很重要的。与许多“好”做法一样,工厂可以产生某些优势,这些优势是您有时想要的,只有正确使用它们才能获得。

factory 通常是对象模型中的另一个类。例如,你经常会得到一个播放器,因为你有一个带有播放器集合的邻居,你会迭代它,对玩家做的事情。或者您从网络对象开始。或者(我猜)你已经有一个播放器,你得到了一个友谊,你从中得到播放器。所以友谊播放器对象的工厂,而播放器友谊对象的工厂!

你有时会有非域名,专用工厂对象的理由。您可能有一个工厂类作为您将开始逻辑的对象的起点。通常,当有很多棘手的方法需要实例化某些对象并且工厂是组织它们的好方法时,它们会被使用。有时您的对象需要使用例如数据层和用户以及上下文进行实例化,并且工厂可以维护这些内容,创建对象,并使您不必在许多不同的构造函数中重复自己。有时工厂可以自动生成各种工具所需的通用引用。

有一种工厂的使用正在迅速增长,值得特别提及。这是使用工厂类向inject dependencies添加误导层,特别是单元测试

我的建议是指如果您没有特定的理由使用工厂对象,请不要担心它们。用优秀的构造函数构建对象。然后添加返回相关对象的属性是很自然的;这些将是你的第一家工厂。这可能是您最初不想担心设计模式的一个很好的例子;设计模式不能带来成功。你做。模式,如各种工厂模式,可以帮助但不能取代基本的面向对象思维。

为什么需要专用的工厂对象,您是否有特定的理由?

答案 1 :(得分:2)

如果没有变化,即。如果您的构建过程是固定的,我会建议最简单的方法:让对象本身负责构建其依赖对象,并建立链接(可能是双向的)。

示例:对于具有子集合的父对象,父对象可以使用addChild方法来确保双向关系的一致性:

  1. 得到孩子的前任父母;如果不为null,则从该旧父项中删除该子项。
  2. 将子级中的父级字段更改为新父级
  3. 将孩子添加到新父母的孩子的集合中。
  4. 如果某些内容有所不同,就像在某些上下文中应该使用的子类一样,那么你必须准确定义不同的内容。只有在找到您的确切需求后,才会出现正确的图案。 : - )

    我们可以帮助完成最后一部分,但您是唯一可以提供所需信息的人......; - )

答案 2 :(得分:2)

KLE对于处理它的方式是正确的,这取决于关系的静态程度。我补充说,Factory类通常镜像对象模型。一种简单的方法可以将它们视为智能对象,知道如何连接模型的不同类。