如何更新不可变对象中的字段
How to update a field in a immutable object
假设如下 class:
@Immutable
public final MyMessageClass {
private String message;
private Date dateLastChange;
private String identifier;
public MyClass(final String message){
this.message = message;
dataLastChange = new Date();
}
public Date lastChange() {
return new Date(dateLastChange.getTime());
}
public String messageValue(){
return message;
}
}
一旦我们构建了这个 class 的对象,
MyMessageClass myMessageObject = new MyMessageClass("Once upon a time ...");
一旦我们完成了一些操作,
logger.info("The message is{}",myMessageObject.messageValue());
logger.info("The last change was done on {}",myMessageObject.lastChange());
它应该从某个地方(例如远程服务)获取 identifier
并将其附加到 message
。但是,如果我这样做:
myMessageObject.setIdentifier(identifier);
我应该破坏了对象的不变性能力。如果是这样,更新 identifier
字段的最佳方法是如何避免调用新的构造函数(因此创建一个新对象)?
所以问题只是因为您想先记录一些东西?不能在构建对象后执行此操作吗?
或者,您可以使用构建器模式,像这样。请注意最后的实例字段 - 即使没有注释,此 class 的实例也是不可变的。
@Immutable
public final MyMessageClass {
private final String message;
private final Date dateLastChange;
private final String identifier;
public MyClass(final MyMessageClass.Builder builder){
this.message = builder.message;
this.dataLastChange = builder.dataLastChange;
this.identifier = builder.identifier;
}
public Date lastChange() {
return new Date(dateLastChange.getTime());
}
public String messageValue(){
return message;
}
public String identifier(){
return identifier;
}
public static final class Builder {
private String message;
private final Date dateLastChange = new Date();
private String identifier;
public Builder message(final String message) {
this.message = message;
return this;
}
public String message() {
return message;
}
public Builder identifier(final String identifier) {
this.identifier = identifier;
return this;
}
public String identifier() {
return identifier;
}
public Date lastChange() {
return new Date(dateLastChange.getTime());
}
public MyMessageClass build() {
return new MyMessageClass(this);
}
}
}
然后您可以逐步构建对象的内容。
MyMessageClass.Builder builder = new MyMessageClass.Builder().message("Once upon a time ...");
logger.info("The message is{}", builder.message());
logger.info("The last change was done on {}",builder.lastChange());
String identifier = // get the identifier from somewhere
MyMessageClass message = builder.identifier(identifier).build();
假设如下 class:
@Immutable
public final MyMessageClass {
private String message;
private Date dateLastChange;
private String identifier;
public MyClass(final String message){
this.message = message;
dataLastChange = new Date();
}
public Date lastChange() {
return new Date(dateLastChange.getTime());
}
public String messageValue(){
return message;
}
}
一旦我们构建了这个 class 的对象,
MyMessageClass myMessageObject = new MyMessageClass("Once upon a time ...");
一旦我们完成了一些操作,
logger.info("The message is{}",myMessageObject.messageValue());
logger.info("The last change was done on {}",myMessageObject.lastChange());
它应该从某个地方(例如远程服务)获取 identifier
并将其附加到 message
。但是,如果我这样做:
myMessageObject.setIdentifier(identifier);
我应该破坏了对象的不变性能力。如果是这样,更新 identifier
字段的最佳方法是如何避免调用新的构造函数(因此创建一个新对象)?
所以问题只是因为您想先记录一些东西?不能在构建对象后执行此操作吗?
或者,您可以使用构建器模式,像这样。请注意最后的实例字段 - 即使没有注释,此 class 的实例也是不可变的。
@Immutable
public final MyMessageClass {
private final String message;
private final Date dateLastChange;
private final String identifier;
public MyClass(final MyMessageClass.Builder builder){
this.message = builder.message;
this.dataLastChange = builder.dataLastChange;
this.identifier = builder.identifier;
}
public Date lastChange() {
return new Date(dateLastChange.getTime());
}
public String messageValue(){
return message;
}
public String identifier(){
return identifier;
}
public static final class Builder {
private String message;
private final Date dateLastChange = new Date();
private String identifier;
public Builder message(final String message) {
this.message = message;
return this;
}
public String message() {
return message;
}
public Builder identifier(final String identifier) {
this.identifier = identifier;
return this;
}
public String identifier() {
return identifier;
}
public Date lastChange() {
return new Date(dateLastChange.getTime());
}
public MyMessageClass build() {
return new MyMessageClass(this);
}
}
}
然后您可以逐步构建对象的内容。
MyMessageClass.Builder builder = new MyMessageClass.Builder().message("Once upon a time ...");
logger.info("The message is{}", builder.message());
logger.info("The last change was done on {}",builder.lastChange());
String identifier = // get the identifier from somewhere
MyMessageClass message = builder.identifier(identifier).build();