创建相互依赖的对象

时间:2010-08-07 17:34:52

标签: php design-patterns oop object

我有一个设计问题,我找不到一个干净,漂亮的解决方案。我正在使用PHP进行开发,但我相信这可能会出现在任何语言中。我的基本问题是我有两个在某个间接层面上具有循环相互依赖性的对象。这意味着我有一个实现Facade模式的类(称之为F),它包含一个对象(B类),它本身需要创建一个A类对象。 A类的构造函数本身需要创建一个外观F =>我对象具有循环的相互依赖性。

我相信我无法解决循环的相互依赖性(这些对象基本上使用状态模式实现了一个带有循环的有限状态机)所以我正在寻找一个干净的解决方案。我自己想出了两种可能的解决方案,但我认为它们都不是特别优雅:

  1. 让A类实现一个setFacade(F $ facace)方法并从构造函数中删除整个Facade,然后在A和Facade创建之后设置它。 A类的对象在没有外观的情况下无法工作,所以这实际上会创建一个A类的对象,在调用setFacade之前它无法做任何事情,它会减少封装并允许在对象运行时替换外观,我也不会不喜欢。

  2. 实现类似于传递给A而不是外观的Promise之类的东西,它可以在创建后立即解析外观。我不想介绍这个额外的间接层,特别是因为我没有比在处理A内部的商业逻辑的方法中实际解决承诺的好地方,这可能a)产生可怕的错误和(更重要的)b)需要需要无论何时调用商务逻辑,我都要检查承诺是否已经解决,或者我现在是否需要解决它。那只是我眼中可怕的设计。

  3. 因此,如果有人能够提出更好的解决方案,或者能够以一个好的论据支持我的一个可能的解决方案,我真的很高兴。

3 个答案:

答案 0 :(得分:2)

循环依赖是一种恶意的恶魔,必须不惜一切代价避免它们,即使它意味着完全重新考虑你的设计并丢掉数小时的工作。 (从维护程序员的角度来说。在你之后需要做一些可怜的笨蛋。)

有几种方法可以查看重构代码,但我所提出的简短的非特定建议是,任何导致循环依赖的对象应该将违规属性,方法等拆分为新对象。然后,两个原始依赖项中的每一个都将依赖于该第三个对象,而不是彼此依赖。 (并确保第三个对象不依赖于原件。)

即使它意味着具有重复或类似的代码,它仍然优于循环依赖(但即使这应该可以通过适当的预先设计来避免。)

答案 1 :(得分:1)

假设您正在使用Facade,因为它是通常定义的(作为管理依赖关系并使其更容易使用复杂API的简化接口),那么“隐藏”(由外观)类都不应该知道哪些类使用立面。从本质上讲,将其视为单一入口点,这意味着B不应该依赖于A,或者A不应该依赖于Facade。

答案 2 :(得分:1)

虽然我无法解决循环依赖问题,但我至少解决了如何创建包含该循环依赖关系的系统的解决方案。

我改变了所有的状态类,不再在构造函数中取出它们的出口点,而是通过一种方法,如果第二次调用它,它将基本抛出异常。

然后我介绍了一个构建器类,它将在我的状态机中创建每个状态,然后使用上面解释的方法设置它们的状态传输连接。因此,只要构建器返回有限状态机,它就会完全设置并准备好使用。每个状态的退出点都不能再被更改,因为设置它们的方法会在调用时抛出异常,因为构建器在创建有限状态机时已经调用过它们。

感谢大家帮助我解决这个问题。