传递整个对象与传递对象的属性

Luc*_*cas 40 java oop performance

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

method1(ObjectA);
method2(ObjectA);
Run Code Online (Sandbox Code Playgroud)

要么

method1(Object1.getField1(), ObjectA.getField2());
method2(ObjectA.getField3());
Run Code Online (Sandbox Code Playgroud)

谢谢你的回答!

chr*_*her 35

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

我写它的方式

如果方法与类相关,我会传递整个对象.我的理由是尽可能地分散课堂知识.我的意思是以下内容.

public void doSomethingRelatedToTheClass(String param)
{
    // Do something with param.
}
Run Code Online (Sandbox Code Playgroud)

我在这里的第一个批评是这个方法假设输入是正确的字段.我的第二个,现在,调用此代码的类需要更多地了解这个方法,因为它必须像这样调用它:

doSomethingRelatedToTheClass(myObject.getValue());
Run Code Online (Sandbox Code Playgroud)

这意味着,如果您发现另一个成员ObjectA在此方法中工作得更好,或者您想要访问其他成员ObjectA,并且您更改doSomething()以反映此更改,则还需要将方法调用更改为:

doSomethingRelatedToTheClass(myObject.getOtherValue(), myObject.getValue());
Run Code Online (Sandbox Code Playgroud)

因此,通过传入整个对象,您将该细节抽象出来,并且该方法可以处理它; 即:

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();
}
Run Code Online (Sandbox Code Playgroud)

当更改为一个类时,会导致其他类的更改,这是一个名为Shotgun Surgery的反模式.

编辑

我有机会在这里回顾我的答案,我稍微修改了我的原始答案,因为我认为它不是适用于所有情况的最佳解决方案.如上所述,如果方法具体与类相关,则该类的实例化(或更优选地,其超类或实现的接口[s])应该是参数.

不是这种情况的时间是功能可以是通用的.泛型函数的示例可能是:

public String[] findNouns(String sentence);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,在句子中查找名词可能适用于大量用例,而不仅仅是您定义的用例.因此,传递值是唯一合理的方法,否则,您将两个逻辑耦合在一起,没有直接关系.名词的发现和你定义的任意对象.

综上所述

  • 如果方法是与对象相关的逻辑,则传入对象

  • 如果该方法与该对象无关,并且该对象仅将其用作实用程序函数,则传入该值并将该函数命名为泛型.

  • 可能出现的一个问题是,通过将整个`ObjectA`传递给函数定义,每个调用API的测试函数都需要用所有字段实例化一个Fake`ObjectA`,即使该函数只使用这些字段的子集.然后,如果在`ObjectA`类上添加一个字段,即使实现没有真正改变,你也需要更改所有这些假对象.通过将工厂用于存根可以避免这种情况,但需要更多代码. (4认同)
  • 另一件事是,在我当前的项目中,我看到很多遗留代码传递了太多数据。如果需要一个属性,并且您正在传递整个对象,以防万一有一天您需要其他属性...... YAGNI (3认同)

maa*_*nus 5

我会说,这取决于。如果方法对参数进行操作而不是需要整个对象,则该方法可能会更清晰、更通用。有时,您已准备好参数(例如,xy),并且必须先将它们聚合到例如 aPoint中,以便能够调用该方法。有时您有一个不同的不相关对象(例如, some ImmutablePoint,显然不是扩展java.awt.Point)并且必须提取坐标并创建一个对象来传递。

通常,如果传递的对象是正确的抽象,那么将其作为一个整体传递是可行的方法。这不是性能问题,而是关于可读性和可维护性。另请参阅德米特法则,这可能会导致对传递对象的依赖性降低。


n4r*_*zul 5

我们来看看一个场景.现在这可能是您的情况,也可能不是,但它说明了一点.

假设你的case中的field1和field2是两个整数,method1将它们相加并返回结果.

如果传入对象,那么该方法只能对这两个字段求和.该方法现在也与这些对象强烈耦合.

另一方面,如果仅传入字段,则在这种情况下,两个整数的方法变得更通用.您现在可以对任意2个任意整数求和,无论它们在哪个对象上.

但总的来说,总是将对象暴露给其他方法和类.这促进了松耦合.

例外

AS maaartinus指出如果例如field1和field2是Points并且method1计算了这两个点之间的距离,那么我必须同意传递两个Point会比传递2 xy整数对(4个参数)更好

希望这可以帮助