面向对象的方法桥

时间:2012-01-05 11:43:34

标签: php oop

我系统中的几个资源使用基于Java集合的对象集合的概念。

此Collection Class(abstract)为另一个具体类提供了基本功能,称为Lists,它允许通过Collection的索引查找对象。

我将使用我的HTTP Headers类作为示例进行解释。

我在其构造函数中有一个这个Lists类的实例。每个HTTP标头字段都通过 Headers :: addHeader()方法添加到集合中。

显然,我有一个名为 getHeaders() getter 方法,它返回Collection的存储,而不是Collection的对象< /强>

因此,如果我需要在此课程之外列出标题,我只需要调用 $ obj - &gt; getHeaders(),我有一个添加了所有对象的ArrayObject。

好的!

但是,最近,出现了使用Lists方法之一 Lists :: find()的必要性,它找到一个对象,甚至不知道对象的名称或其在Collection的存储中的具体位置。 / p>

由于Lists对象位于私有属性中,因此Headers :: getHeaders()返回Collection Storage,我不想违反封装,通过使属性成为公共属性,我无法访问此方法。 / p>

除了功能之外,我编写的所有内容都必须在视觉上优雅,并创建另一个getter方法,假设getHeadersLists()会产生如下调用:

$obj -> getHeadersLists() -> find( 'foo' );

这太丑了!

所以,我在Headers Class中快速添加了一个__call(),它运行良好:

$obj -> find( 'foo' );

但我认识的人(他非常精通面向对象主题)告诉我这是错误的。

我的论点纯粹是关注可读性,他反驳说“在面向对象,魔术方法和可读性方面不能共存”。

那又怎样?我应该怎么做才能在这两个类之间创建这个“桥梁”,而不使用_call()并保留Object Orientation的原则?

我知道,我可以在Headers :: getHeaders()中返回Collection对象并使用类似的东西:

$obj -> getHeaders() -> find();

但我学到的关于面向对象的东西是责任。正如其声明所说,这种方法的责任在于返回所有添加的Headers,而不是外部对象。

2 个答案:

答案 0 :(得分:1)

我打算用鲍勃叔叔的单一责任原则a.k.a(S.O.L.I.D的大S)打你。您可以在Principles Of OOD文章中阅读更多内容。也可以直接回答您的问题Tom Dalling's very nice article and example

Single Responsibility Principle. Acknowledgement I have no rights or claims on this image.

隐藏getHeaders()函数调用时出现的问题,返回类型为 Lists 的对象,然后看起来你正在调用该对象,并且它有一个名为find的函数“它不应该有”因为找到正确的标题不是他的责任。

我能理解你的责任方法。

你说:当我调用getHeaders()时,我不应该被迫进一步操纵结果以获得我想要的结果。

你的这个建议完全正确。但是要实现这个结果,隐藏带有合成糖的getHeaders()函数调用完全错误。因为它会误导我。

考虑到我作为第三方阅读您的代码,我会立即假设该类的find()函数非常具有误导性。此外,我会拒绝这个find()函数,因为从标题列表中查找不是来自对象的责任,这只是一个不必要的附加组件或错误。所以你的同事也是正确的:D。

我认为迫使你调用 find()以便能够使用标题类型对象的情况应该归咎于此。

我对你的困境的建议是这样的。

  1. 这个对象最应该有一个名为getHeaders()的函数。不要改变它。它应该返回所有标题。
  2. 创建一个名为getRelatedHeaders(“foo”)或 getFooHeaders()的第二个函数,它以封装的方式调用getHeaders(),而不是对它们使用find(“foo”)并返回你的“foo” “标题。
  3. 现在我的朋友只剩下一个小小的消息了。我相信你的讨论会引发一个更有趣的问题,你和你的队友应该问这个问题。

    几乎总是,如果你需要获得一个对象的某些属性并对它们采取行动。然后,您还应该能够将该功能封装到该对象/类中。当你获得一个对象属性并使用它来做某事然后把它放回去时,几乎总是代码味道。

      

    为什么这个对象没有尽职尽责,但你是   为他操纵他的财产?

    感谢您的时间,我希望我能帮助您:D。

答案 1 :(得分:0)

这就是为什么在PHP中有一个“受保护”的范围,就像其他O.O.编程语言。

如果您知道,后代类可以访问“受保护”成员,但不能将其作为公共访问。

作为一个建议,我通常不会使用“私人”,而是“受保护”,原因与您的帖子相同。