Java 不可变POJO和单字段更改的Sane模式

Java 不可变POJO和单字段更改的Sane模式,java,immutability,Java,Immutability,通常我希望我所有的POJO都是不可变的(因为Java理解不可变性,所以只包含final字段)。但在我当前的项目中,一个不变的模式是我需要从POJO更改单个字段。在这个场景中使用不可变的POJO看起来很麻烦 你会如何让POJO包含一堆字段,对于每个字段,你应该能够说“请给我一份POJO的副本,但这一个字段已更改” 这里的大加号是我可以与可组合函数一起使用的东西。“从这个不可变的pojo开始,然后基本上通过一堆一元运算符将其推送,然后返回新的不可变的pojo” 是的,这是一种相当常见的模式-通常有一

通常我希望我所有的POJO都是不可变的(因为Java理解不可变性,所以只包含
final
字段)。但在我当前的项目中,一个不变的模式是我需要从POJO更改单个字段。在这个场景中使用不可变的POJO看起来很麻烦

你会如何让POJO包含一堆字段,对于每个字段,你应该能够说“请给我一份POJO的副本,但这一个字段已更改”


这里的大加号是我可以与可组合函数一起使用的东西。“从这个不可变的pojo开始,然后基本上通过一堆一元运算符将其推送,然后返回新的不可变的pojo”

是的,这是一种相当常见的模式-通常有一组带有前缀
方法。每个带有*
方法的
都会“更改”单个字段,因此您可以:

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, ...);
}

我在这种方法中使用了“伪突变子”这个词——这是一种听起来有点像是在变异的方法,但更像是在创建克隆,变异克隆,然后以“冻结”状态返回给你。

该死的飞碟。。。能给我你的签名吗?官方名称是什么(如有);从来都不知道这个名字(它不是一个花哨的构造器),是吗?@kolossus:不,这不是一个构造器模式——我不知道这个模式的名字;根据我的编辑,我称这些方法为伪变异体,但这只是我对它们的称呼。在我看来,它更像是原型的变体(因为每个对象都可以创建自身的可变克隆)。我实现了static Builder.from(person).withFirstName(firstName).build();在Builder.from(persson)中创建新的Builder并从person POJO复制所有字段。下面是一篇关于具有优化状态的构建器模式的文章: