Java 我应该如何为以下场景设计方法签名

Java 我应该如何为以下场景设计方法签名,java,architecture,design-patterns,Java,Architecture,Design Patterns,如果您有一个输入参数可能是输出的方法 假设我们有一个save方法,该方法生成一个自动生成的id,客户机在调用save()后可能会感兴趣使用该id 人 id(自动生成) 名字 。。。(其他领域) 您应该这样设计方法签名: public Person save() { // do your save stuff return this; } 一, 客户端调用: personService.save(person); System.out.println(person.getId

如果您有一个输入参数可能是输出的方法

假设我们有一个save方法,该方法生成一个自动生成的id,客户机在调用save()后可能会感兴趣使用该id

  • id(自动生成)
  • 名字
  • 。。。(其他领域)
您应该这样设计方法签名:

public Person save() {
    // do your save stuff
    return this;
}
一,

客户端调用:

personService.save(person);
System.out.println(person.getId());
person = personService.save(person);
System.out.println(person.getId());
二,

客户端调用:

personService.save(person);
System.out.println(person.getId());
person = personService.save(person);
System.out.println(person.getId());
我们知道,在接收对象的方法调用中,传递对该对象的引用,因此只要其他人具有相同的引用,对该对象所做的任何更改都将被其他人感知。但是在远程调用的情况下,会发生序列化/反序列化,因此我的对象引用与远程服务对象的引用不同。因此,即使在那里进行了更改,客户也不会注意到差异

此时,我知道该方法不会是远程调用,因此我可以使用第一个签名来设计它。但是,如果将来这种情况发生变化,需要作为远程调用来调用,该怎么办呢

所以我的问题是: 我是否应该设计API,认为API将来可能会作为远程调用调用,而不使用对象参数作为向客户端返回值的方式(2),还是应该根据服务不远程的实际情况设计API(1)


谢谢

为什么不两个都做呢?使用第二个签名,在本地修改person,暂时只返回对同一个人的引用。这样,将来根据任何需要更改它都不会改变API,当前用户仍然可以使用您的第一种方法

也就是说,总的来说,我对改变参数的方法感到不舒服,除非这是它们的唯一目的,并且它们的命名和文档记录表明了这一点。从“该方法在做什么,我从中获得了什么新信息”的角度来看,我可能会选择以下签名:

public ID save(Person);

我建议使用第一种方法,因为对象很少单独使用。Person对象通常由其他实体(如Employee)引用。如果您创建一个新实例,您将使整个对象图无效,相信我,您不想在深度复制中乱搞

至于未来RPC的可能性,无论您将使用什么来实现这一点,它都很可能在操作提交后更新ID字段


@CPerkins-对象通过“引用值”传递,以确保绝对正确;)

两者都可以;让
save()
返回新ID并使用
getId()
方法。从“setter”(一种改变状态的方法)返回值有很多先例——java Collections API一直都在这样做,例如
Map.remove(Object)
返回
布尔值

流畅的界面

还有另一种模式,你可能需要考虑的是模式。使用流畅的API,您可以从每个方法返回对象(即
this
),否则将返回
void
。这使调用方可以“链接”方法调用。使用流畅的界面,您的代码如下所示:

public Person save() {
    // do your save stuff
    return this;
}
如果要在保存后输入ID,请编写以下代码:

save().getId();
简单!这种模式也已在许多现有java代码中使用,尤其是hibernate,如中所示


如果Java中的对象没有通过引用传递,那么我建议使用fluent。一切都是通过值传递的——它看起来就像是通过引用传递对象,因为传递的值就是引用。但是有一个显著的区别。尝试编写一个交换两个对象参数的方法。我的意思是,如果服务在同一个JVM中,那么传递给服务的引用将是同一个引用,比如说本地EJB。但是在远程EJB的情况下,指向客户端对象的引用将不同,并且对服务中的对象所做的更改不会反映在客户端对象上。如果唯一受影响的属性是id,这可能会起作用。但是如果修改了多个属性会怎么样呢。例如,假设此人的creationDate是在该调用中修改的属性。创建一个封装可以更新的元数据的类。将其称为SaveData或SaveSpec。Person可以具有该类型的字段,也可以具有采用该类型并更改其状态的方法。Fluent接口很好,但根本的问题是返回的Person对象是否应与参数为同一实例。Oops!略过那一点:)