Johan S Johan S - 6 months ago 11
Java Question

Java Model Objects design

So I've been reading some Effective Java! And one of the most inspiring sections of the book is the Immutable Object/Builder section where Bloch writes about the "Builder" - class instead of just POJOs.

NOTE: I am talking about model objects here: like for instance an Article or a Car.

This is how I wrote these objects before:

public class Car {

private String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}
}


Now as you see this design is deficient in a number of ways, it requires mutability and you have to construct the object with first the constructor then setting the name.

Now of course you can make the
name
field final and use it as an argument in the constructor but then if you have a large object wrapping for instance a number of SQL - Tables then you will have an ugly constructor like this:

public Car(int horsepowers, String name, String brand, int yearManufactured,
User owner, List<User> previousOwners) {
//Set the values
}


This becomes unreadable when creating the object, and this is just six fields!

So, Bloch suggests the following (with immutability)

public class Car {

public static class Builder {

private String name;

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

public Car build() {
reeturn new Car(this);
}
}

private final String name;

private Car(Builder builder) {
name = builder.name;
}

public String getName() {
return name;
}
}

//Construction example
Car car = new Car.Builder().setName("Speedy").build();


Now this gives us immutability! And if you have some objects that arent primitive or immutable just copy them in the
Builder
's setters and copy them again in the
Car
's getters.

But it's very wordy and I've been using constructor arguments if the class is small enough.
If a class needs a mutable field I just make that field mutable, if the class has enough properties (> 4 something).

Another problem is when working with android and the class has for example a
Bitmap
, then you have to return the actual bitmap and not copy it because that is rather performance - expensive.

I've seen tons of questions like this but I can't seem to find a good answer on this question: is there any standard on these designs and how are their design? What are the benefits/defeceits?

Thanks in advance!

EDIT:

The question is:

What is the best way to construct an object model that should be immutable and with A) a small number of fields and B) a large number of fields? How to handle the
Bitmap
issue mentioned above and similar issues? Making certain fields mutable?

Sorry for being vague.

Answer

The Design Patterns book is the alpha and the omega of design patterns currently. It is not new however but it seems that it passed the test of time.

You can read detailed real life examples of each design pattern, how do they relate to each other, how and when to use them and a thorough explanation for each. The Builder pattern is included of course.

As to answer your question I can present my views although they are of course not authoritative.

I think that if you have a small number of fields you can go with using the constructor. If you take checkstyle for example it fires a warning over 7 parameters.

If you know for sure however that you will refactor that class soon or you will have to extend it I think the Builder pattern is better since it is easier to refactor. Refactoring constructors is never fun.

If you are over 7 parameters I think the Builder is far better. I've been using it in the current project I'm working on extensively.

Please note that by using the Builder pattern you don't say that "Okay, I'm an immutable object builder". You say that "Okay, I'm building parameterized objects". It is therefore not a problem that you have a set of mutable fields in your class. If you however name your class like ImmutableFooDTO and later you add mutable fields it leads to confusion.

So if there is a set of fields which must not be mutable then mark them final and use a constructor/builder and provide setters for the mutable ones.