When I want to make an immutable type with a lot of attributes.  I
generally like to use a static inner class as a builder object.
Here's an example with just two attributes.


public final class Person{

   private final String firstName;
   private final String lastName;

   public Person(String firstName, String lastName){
      super();
      this.firstName = firstName;
      this.lastName = lastName;
   }

   public String getFirstName(){return firstName;}
   public String getLastName(){return lastName;}


   public static class Builder {
      private String firstName;
      private String lastName;

      public Builder setFirstName(String firstName){
          this.firstName = firstName;
          return this;
      }

      public Builder setLastName(String lastName){
          this.lastName = lastName;
          return this;
      }

      public Person newPerson(){
          return new Person(firstName, lastName);
      }
  }

}


Then in my client code, I would do:

    Person keith = new Person.Builder().setFirstName
("Keith").setLastName("Haber").newPerson();

Or if I need to instantiate a lot of similar objects, I can hang on to
my Builder object.  (Could be handy for constructing relatives, I
suppose.)

A nice thing about this approach is that I get the benefit of readable
setters instead of working with long lists of meticulously ordered
constructor arguments (not so big a deal with two attributes, but very
helpful when working with six or more attributes), but my immutable
objects don't have setters at all.

And by making the builder class a static inner class, it's obvious
which builder classes go with which immutable types -- it's always
named <immutable type name>.Builder.

In episode 219 they talked about objects having a "construct phase"
with setters and a "use phase" when the object construction is
"finished."  To my mind this approach is reasonably close to that
idea.

Keith


On Dec 3, 10:58 pm, hlovatt <[EMAIL PROTECTED]> wrote:
> In 219 there was a long discussion about setting up an object and then
> making it immutable. There are a couple of ways of doing this in Java
> already:
>
> public class FooArgs {
>   public int x = 1; // 1 is default
>   public int y = 2;
>   public int z = 3;
>   ...
>
> }
>
> public class Foo {
>   public Foo( FooArgs args ) { ... }
>   ...
>
> }
>
>   Foo foo = new Foo( new FooArgs() {{ x = 2 }} );
>
> Another option is an immutable and mutable versions that inherit from
> a common base and implement a standard conversion interface. First the
> standard interface:
>
> public interface ImmutableValueConversions {
>   Immutable toImmutable() throws IllegalStateException;
>   Value toValue();
>
> }
>
> Below is an integer example that uses an abstract class as the base of
> the hierarchy. You can also use interfaces. The abstract class is:
>
>     8:public abstract class AbstractInteger extends AbstractValue
>     9:    implements ImmutableValueConversions, InstanceFactory {
>    10:    public abstract int getValue();
>    11:
>    12:    public abstract AbstractInteger instanceOfSelf( int value );
>    13:
>    14:    public AbstractInteger add( final int rhs ) {
>    15:        return instanceOfSelf( getValue() + rhs );
>    16:    }
>    17:}
>
> Then the immutable version:
>
>     9:public final class ImmutableInteger2 extends AbstractInteger
>    10:    implements Immutable {
>    11:    private final int value;
>    12:
>    13:    public ImmutableInteger2( final int value ) {
>    14:        this.value = value;
>    15:    }
>    16:
>    17:    public int getValue() {
>    18:        return value;
>    19:    }
>    20:
>    21:    public Immutable toImmutable() {
>    22:        return this;
>    23:    }
>    24:
>    25:    public Value toValue() {
>    26:        return new ValueInteger( value );
>    27:    }
>    28:
>    29:    public AbstractInteger instanceOfSelf( final int value ) {
>    30:        return new ImmutableInteger2( value );
>    31:    }
>    38:}
>
> And the value version:
>
>     9:public final class ValueInteger extends AbstractInteger {
>    10:    // Not final, this is the value version
>    11:    private int value;
>    12:
>    13:    public ValueInteger( final int value ) {
>    14:        this.value = value;
>    15:    }
>    16:
>    17:    public int getValue() {
>    18:        return value;
>    19:    }
>    20:
>    21:    // Setter, this is the value version!
>    22:    public void setValue( final int value ) {
>    23:        this.value = value;
>    24:    }
>    25:
>    26:    public Immutable toImmutable() {
>    27:        return new ImmutableInteger2( value );
>    28:    }
>    29:
>    30:    public Value toValue() {
>    31:        return new ValueInteger( value );
>    32:    }
>    33:
>    34:    public AbstractInteger instanceOfSelf( final int value ) {
>    35:        return new ValueInteger( value );
>    36:    }
>    37:
>    38:    // Set and add combined (+=), this is the value version!
>    39:    public ValueInteger setAdd( final int rhs ) {
>    40:        value += rhs;
>    41:        return this;
>    42:    }
>    49:}
>
> Then you can use these classes like this:
>
>   ImmutableInteger i = (ImmutableInteger)( new ValueInteger().setValue
> ( 2 ).toValue() );
>
> My own pet project, PEC, is an extensible compiler that can enforce
> patterns, the above immutable pattern can be enforced. More details
> from:
>
>  http://pec.dev.java.net/nonav/frontpage.html
>
> What do others do?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to