不可变 pojo 和单个字段更改的合理模式

Sane pattern for immutable pojos and single field changes

通常我希望我所有的 POJO 都是不可变的(好吧,只包含 final 字段,因为 Java 理解不可变性)。但是对于我当前的项目,一个不变的模式是我需要从 POJO 更改单个字段。在这种情况下使用不可变的 POJO 似乎很麻烦。

您将如何使用带有一堆字段的 POJO,并且对于每个字段您应该能够说 "please give me a copy of this POJO but with this one field changed"?

这里的一大优点是我可以将其与可组合函数一起使用。 "Start with this immutable pojo, then basically push it through bunch of UnaryOperators and give me back new immutable pojo"。

是的,这是一个相当普遍的模式 - 通常有一堆带有 with 前缀的方法。每个 with* 方法 "changes" 一个字段,因此您可以:

Person jon = new Person("Jon", "Skeet");
Person holly = jon.withFirstName("Holly"); // Holly Skeet

您也可以将调用链接在一起:

Person fred = jon.withAge(...).withFirstName("Fred").withJob(...);

请注意,如果您最终更改了具有 N 个字段的 POJO 中的 K 个字段,您将创建 K 个对象并需要 K * N 个分配。

实现通常只是使用现有字段值和新字段值调用大型构造函数的问题:

public Person withFirstName(String newFirstName) {
    return new Person(newFirstName, lastName, job, age, ...);
}

我为这种方法使用了术语 "pseudo-mutator" - 这种方法听起来有点像在改变某些东西,但它更像是在创建一个克隆,改变克隆,然后返回它给你 "frozen" 状态。