The Builder implementa Cloneable y anula clone() y en lugar de copiar todos los campos del generador, la clase inmutable conserva un clon privado del generador. Esto hace que sea más fácil devolver un nuevo generador y crear copias ligeramente modificadas de una instancia inmutable.¿Es esta una implementación válida de Java de una clase inmutable y el patrón de Constructor?
De esta manera puedo ir
MyImmutable i1 = new MyImmutable.Builder().foo(1).bar(2).build();
MyImmutable i2 = i1.builder().foo(3).build();
La interfaz Cloneable se dice que está un poco roto, pero nada de esto viola las buenas prácticas de codificación Java, ¿hay algún problema con esta construcción?
final class MyImmutable {
public int foo() { return builder.foo; }
public int bar() { return builder.bar; }
public Builder builder() { return builder.clone(); }
public static final class Builder implements Cloneable {
public Builder foo(int val) { foo = val; return this; }
public Builder bar(int val) { bar = val; return this; }
public MyImmutable build() { return new MyImmutable(this.clone()); }
private int foo = 0;
private int bar = 0;
@Override public Builder clone() { try { return (Builder)super.clone(); } catch(CloneNotSupportedException e) { throw new AssertionError(); } }
}
private MyImmutable(Builder builder) { this.builder = builder; }
private final Builder builder;
}
Estaba tratando de cortar algunas esquinas y evitar copiar campos explícitamente. El método "basedOn" es muy claro pero me obligaría a copiar campos (nuevamente). Tal vez estoy siendo muy perezoso. – Aksel
Excelente sugerencia del método basedOn :) – troig