如何更新不可变对象中的字段

时间:2015-05-04 08:47:22

标签: java oop immutability

假设以下课程:

@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;
 }

}

一旦我们构建了这个类的对象,

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字段以避免进行新的构造函数调用(创建新对象)的最佳方法是什么?

1 个答案:

答案 0 :(得分:3)

所以问题只是因为你想先记录一些东西?在构造对象后,你不能这样做吗?

或者,您可以使用类似的构建器模式。请注意最终的实例字段 - 即使没有注释,此类的实例也将是不可变的。

@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();