The builder approach is another common alternative. Compared to the
first method I showed it is really just a preference of the syntax
(and you can put FooArgs inside Foo and use Foo.Args if you prefer).
The second method I showed is closer to a builder, but it has a number
of differences.

You have a common base class, AbstractInteger, in the example. Within
the base class you can put methods, fields, etc. that are common to
the mutable and immutable forms. You can also program to
Abstractinteger when you don't care if you are given a mutable or
immutable form.

The conversion from mutable to immutable isn't one way. You can
convert back and forward. So for example if you made one object and
then wanted to derive a second from the first you can. EG

public ImmutableInteger add2( AbstractInteger i ) { return i.toValue
().setAdd( 2 ).toImmutable(); }

Note the function can take immutable and mutable forms and therefore
demonstrates both the above points.

You can also program to the convertion interface, e.g. for collections
- see 
http://pec.dev.java.net/compile/javadoc/pec/compile/immutable/ImmutableArrayList.html

On Dec 5, 3:45 am, Keith Haber <[EMAIL PROTECTED]> wrote:
> 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