在不破坏不变性的情况下更新不可变对象

时间:2016-04-04 20:01:54

标签: java performance scala immutability immutable-collections

如何在不破坏不可变性的情况下从另一个不可变对象获取更新的不可变对象。类似于Scala中的实现方式或者它们在Immutables库中的实现方式。

我怎样才能实现这样的目标  Customer.Builder.from(anotherCustomer).replaceOrder(oldOrder,newOrder)。随着(newName)将.build()

重用旧对象并对我想要的所有更改进行排队,以便构建一个新对象。

我正在使用Java。

4 个答案:

答案 0 :(得分:4)

public class Customer {
    private String name;    
    private Order order

    private Customer(CustomerBuilder builder) {
        this.name = builder.name;
        this.order = builder.order;
    }

    public Customer replace(Order order) {
        return new CustomerBuilder().name(this.name).order(order).build();
    }

    public static class CustomerBuilder {
        private String name;    
        private Order order

        public CustomerBuilder name(String name) {
            this.name = name;
            return this;
        }

        public CustomerBuilder order(Order order) {
            this.order = order;
            return this;
        }

        public Customer build() {
            return new Customer(this);
        }
    }
}

答案 1 :(得分:1)

我推荐这本书涵盖这个主题: https://www.amazon.ca/Effective-Java-Edition-Joshua-Bloch/dp/0321356683

我知道更新不可变对象的最好方法是返回对象的修改副本,比如java String

    String uppercase = "hello".toUpperCase()

我很容易使用流利的打字

    String uppercasewithoutletterL = "hello".toUpperCase().replace("L","")

答案 2 :(得分:1)

这是一个小小的递归函数,可创建更改的不可变对象。它重新创建每个包含更改的嵌套对象。

const changeImmutable = (immutable: any, path: string[], newVal: any): any => {
  if(path.length) {
    let copy = Array.isArray(immutable) ? [...immutable] : {...immutable};
    copy[path[0]] = changeImmutable(copy[path[0]], path.slice(1), newVal);
    return copy;
  }
  return newVal; 
};

用法示例

let immutableObj = {a: {b: [{c: 'foo'}]}};

// change 'foo' to 'bar'
let newImmutableObj = changeImmutable(immutableObj, ['a', 'b', 0, 'c'], 'bar');

答案 3 :(得分:0)

您可以在对象类型中实现Cloneable接口。 另一种选择是为不可变对象提供构建器,可以从现有对象创建新实例。像those fellas做的......