2014-01-15 140 views
26

我正在考虑为我的应用程序提供的解决方案。情况如下:我有一个类,它带有一个方法,它将ObjectA作为输入参数并调用几个小方法,这些方法中的每一个都需要ObjectA的某些部分(它们不重叠,即method1()需要ObjectA.field1ObjectA.field2,method2()需要ObjectA.field3等等......)现在的问题是:鉴于通用的良好代码实践和性能,最好将ObjectA传递给这些方法中的每一个,以便它们可以自行提取它们需要的值,或者更好传递它们的值?我的意思是:传递整个对象vs传递对象的属性

method1(ObjectA); 
method2(ObjectA); 

method1(Object1.getField1(), ObjectA.getField2()); 
method2(ObjectA.getField3()); 

感谢您的答案!

+5

我觉得第一个选项是更好..外部世界不需要知道你的函数内部与对象..这样做(即哪些领域它访问。) – TheLostMind

+4

这完全是你的需要。如果您不希望其他方法修改对象的字段,则不要传递对象引用。只需传递所需的值。如果不是,那么最好传递对象引用,并在需要时使用它的值,而不是在方法调用中添加那么多参数。 – SudoRahul

+1

这是一个很好的做法,使代码尽可能简单易懂和清晰。在这种情况下,我怀疑没有性能差异,或者它太小而无法衡量。 –

回答

28

请记住,使用您的代码,您实际上并未传递ObjectA。也就是说,您将参考类型传递给ObjectA,因此在性能注释中,传递String对象引用和ObjectA对象引用之间的差异可以忽略不计。

的方式我会写它

我会通过整个对象,如果该方法是恰当的类。我的推理是尽可能地分解课堂知识。我的意思是以下。

public void doSomethingRelatedToTheClass(String param) 
{ 
    // Do something with param. 
} 

我的第一个批评是这种方法假定输入是正确的字段。我的第二个,就是现在,这个类调用此代码需要知道一点点关于这个方法,因为它有这样称呼它:

doSomethingRelatedToTheClass(myObject.getValue()); 

而这句话的意思是,如果你发现另一的ObjectA成员工作这个方法里面更好,或者您要访问的ObjectA其他成员,并更改doSomething(),以反映这种变化,你也需要改变方法调用,以:通过传递

doSomethingRelatedToTheClass(myObject.getOtherValue(), myObject.getValue()); 

所以整个对象,将这些细节抽象出来,并且该方法可以处理它;即:

doSomethingRelatedToTheClass(myObject); // Doesn't need to know what you do with it. 

public void doSomethingRelatedToTheClass(ObjectA object) 
{ 
    String val = object.getValue(); 

    String otherVal = object.getOtherValue(); 
} 

当更改一个类,在其他类别的变化的结果,这就是所谓的Shotgun Surgery反模式。

编辑

我有机会在这里查看我的回答,我已经修改了我原来的答复略有因为我相信它不是为所有情况下的最佳解决方案。如上所述,如果某个方法与某个类具体相关,那么该类(或者更优选地,其超类或实现的接口[s])的实例应该是参数。

现在不是这种情况的时候,功能可能是通用的。泛型函数的一个例子可能是:

public String[] findNouns(String sentence); 

在这种情况下,发现在一个句子中的名词可能适用于大量的使用案例,而不仅仅是你所定义的用例。因此,传递价值是唯一明智的方法,因为否则,你将两个逻辑连接在一起,这两个逻辑没有直接的关系。名词和你定义的任意对象的发现。

总结

  • 如果该方法是与对象相关的逻辑,通过在对象

  • 如果该方法无关与对象,并且对象只是将它用作实用函数,然后传递值并一般地命名该函数。

+4

+1为详细答案..:P – TheLostMind

+1

可能出现的一个问题是,通过将整个ObjectA传递给函数定义,每个调用API的测试函数都需要实例化一个包含所有字段的Fake ObjectA。即使函数只使用这些字段的一个子集。然后,如果在ObjectA类上添加一个字段,即使实现没有真正改变,也需要更改所有这些假对象。这是可以通过使用工厂存根来避免的,但需要更多的代码。 –

+0

另一件事是,在我目前的项目中,我看到很多遗留代码传递了太多的数据。如果需要一个属性,并且你正在传递一个完整的对象,以防万一某天你需要其他属性... YAGNI – kiedysktos

3

我想说,这取决于。如果一个方法对参数进行操作而不是要求整个对象,则该方法可能会更清晰和更通用。有时候你已经准备好了论据(例如,xy),并且必须首先将它们聚合成例如一个Point为了能够调用该方法。有时你有一个不相关的对象(例如,一些ImmutablePoint,显然不是延伸java.awt.Point),并且必须提取坐标并创建一个要传递的对象。

通常,如果传递的对象是正确的抽象,那么将它作为一个整体传递是一条可行的路。这不是一个性能问题,而是关于可读性和可维护性。另请参阅Law of Demeter,这可能导致对传递对象的松散依赖。

4

让我们来看一个场景。现在这可能或可能不是你的情况,但它说明了一点。

可以说你的情况下,field1和field2是两个整数,method1将它们相加并返回结果。

如果您传入对象,那么该方法只能总结这两个字段。该方法现在也与这些对象紧密结合。另一方面,如果只传递字段,这种情况下的两个整数就会变得更通用。现在您可以对任意2个任意整数进行求和,而不管它们在哪个对象上。

一般来说,尽可能少地暴露你的对象到其他方法和类。这促进了松耦合。

例外

AS maaartinus指出如果例如Field 1和场2分别为点与方法1来计算这两个点之间的距离,那么我不得不同意,传递两个点会比使2的xy整数对更好(4个参数)

希望这有助于