NetBeans 7.2 – New Refactoring option ‘Replace Constructor with Builder…’

Some weeks ago version 7.2 of the NetBeans IDE was released (download at http://netbeans.org/downloads/index.html).

This version includes a nice new option to refactor your code.

The Builder Pattern

The Builder Pattern (amongst others made popular by Joshua Bloch’s 2nd edition of ‘Effective Java’) is very well suited for classes that have a lot of optional parameters for their constructors.

Some of its advantages are:

  • It makes your code more concise and easier to read
  • You can reuse a builder to instantiate similiar objects easier
  • You can avoid copy & paste bugs that can occur when copying code with many setters

Without the Builder Pattern you have two options when faced with many optional parameters: Either you provide only some constructors which forces the client to specify parameters, that are not really needed/wanted, or you provide a constructor for every single combination of the optional parameters. This leads to a more flexible usage when creating instances but requires a huge number of overloaded constructors.

With the Builder pattern you create a dedicated ‘…Builder’ class which helps you to create instances of the desired class. This is achieved by setter-like methods that return the current instance of the builder, which allows method chaining.

 

Refactoring with NetBeans 7.2

Consider this simple POJO:

public class Car {
    private String manufacturer;
    private String model;
    private int horsePower;
    private int numOfSeats;
    private Color color;
    private String cylinder;
    private double length;
    private double width;
    private double price;

    public Car (String manufacturer, String model, int horsePower
            , int numOfSeats, Color color, String cylinder, double length
            , double width, double price) {
        this.manufacturer = manufacturer;
        this.model = model;
        this.horsePower = horsePower;
        this.numOfSeats = numOfSeats;
        this.color = color;
        this.cylinder = cylinder;
        this.length = length;
        this.width = width;
        this.price = price;
    }
}

In this case we have only one constructor with all parameters. But what would you do if you would want to create a Car object with just its manufacturer and model? You would either have to pass in several null/0 values into the given constructor or create another constructor.

The Builder Pattern helps to make the process of instantiation a lot more flexible. With NetBeans 7.2 you can automatically generate a Builder class in a few seconds.

Click on the ‘Refactor’ menu and on ‘Replace Constructor with Builder…’

Following dialog is shown:

Here you have the option to specify default values for some variables.

The resulting class looks like this:

public class CarBuilder {
    private String manufacturer;
    private String model;
    private int horsePower;
    private int numOfSeats;
    private Color color;
    private String cylinder;
    private double length;
    private double width;
    private double price;

    public CarBuilder() {
    }
    public Car createCar() {
        return new Car(manufacturer, model, horsePower, numOfSeats, color
                , cylinder, length, width, price);
    }
    public CarBuilder setManufacturer(String manufacturer) {
        this.manufacturer = manufacturer;
        return this;
    }
    public CarBuilder setModel(String model) {
        this.model = model;
        return this;
    }
    public CarBuilder setHorsePower(int horsePower) {
        this.horsePower = horsePower;
        return this;
    }
    public CarBuilder setNumOfSeats(int numOfSeats) {
        this.numOfSeats = numOfSeats;
        return this;
    }
    public CarBuilder setColor(Color color) {
        this.color = color;
        return this;
    }
    public CarBuilder setCylinder(String cylinder) {
        this.cylinder = cylinder;
        return this;
    }
    public CarBuilder setLength(double length) {
        this.length = length;
        return this;
    }
    public CarBuilder setWidth(double width) {
        this.width = width;
        return this;
    }
    public CarBuilder setPrice(double price) {
        this.price = price;
        return this;
    }
}

You have a public constructor, methods for each attribute of the Car class and a createCar() method to finally create you Car object.

Use can use it like in this example:

public class CarCreator
{
    public static void main(String[] args)
    {
        Car audi = new CarBuilder().setManufacturer("Audi").setModel("A4")
                .createCar();
        Car toyota = new CarBuilder().setManufacturer("Toyota")
                .setModel("Highlander").setHorsePower(187).setColor(Color.BLACK)
                .createCar();
        Car dodge = new CarBuilder().setManufacturer("Dodge")
                .setModel("Avenger").setHorsePower(173).setCylinder("V6")
                .setLength(4.84).setWidth(1.78).createCar();
    }
}

Independent of the number and type of optional parameters the process of instantiation stays the same and you will not need any new overloaded constructors.

Personally I find the ‘set’ prefix to be unnecessary for Builder classes, because it seems verbose and almost looks like ‘normal’ setters. Additionally I do not really like the public constructor, as I prefer a factory method to obtain a Builders instance.

My version of a Builder class would look like this:

public class CarBuilder2 {
    private String manufacturer, model, cylinder;
    private int horsePower, numOfSeats;
    private Color color;
    private double length, width, price;

    private CarBuilder2() {
    }
    public static CarBuilder2 create() {
        return new CarBuilder2();
    }
    public Car build() {
        return new Car(manufacturer, model, horsePower, numOfSeats, color
                , cylinder, length, width, price);
    }
    public CarBuilder2 manufacturer(String manufacturer) {
        this.manufacturer = manufacturer;
        return this;
    }
    public CarBuilder2 model(String model) {
        this.model = model;
        return this;
    }
    public CarBuilder2 horsePower(int horsePower) {
        this.horsePower = horsePower;
        return this;
    }
    public CarBuilder2 numOfSeats(int numOfSeats) {
        this.numOfSeats = numOfSeats;
        return this;
    }
    public CarBuilder2 color(Color color) {
        this.color = color;
        return this;
    }
    public CarBuilder2 cylinder(String cylinder) {
        this.cylinder = cylinder;
        return this;
    }
    public CarBuilder2 length(double length) {
        this.length = length;
        return this;
    }
    public CarBuilder2 width(double width) {
        this.width = width;
        return this;
    }
    public CarBuilder2 price(double price) {
        this.price = price;
        return this;
    }
}

I just changed the constructor to be private, added a factory method and erased the ‘set’ prefixes. With this Builder class the previous example looks like this:

public class CarCreator
{
    public static void main(String[] args)
    {
        Car audi = CarBuilder2.create().manufacturer("Audi").model("A4")
                .build();
        Car toyota = CarBuilder2.create().manufacturer("Toyota")
                .model("Highlander").horsePower(187).color(Color.BLACK)
                .build();
        Car dodge2 = CarBuilder2.create().manufacturer("Dodge")
                .model("Avenger").horsePower(173).cylinder("V6").length(4.84)
                .width(1.78).build();
    }
}

It is up to your personal taste what you like more, but in my opinion, this code is more expressive and concise.

Conclusion

The usage of the Builder Pattern heavily increases the flexibility in the creation process
for classes with many optional parameters. Furthermore, your code is much more readable and easier to understand because you have “named” parameters.

The new ‘Replace Constructor with Builder…’ option in NetBeans 7.2 is very nice to generate Builder classes with just a few clicks, but I hope for more flexibility (like a checkbox to skip the ‘set’ prefixes) in future releases.

Short URL for this post: http://blog.oio.de/FduoY
This entry was posted in Did you know?, Java Basics and tagged , , , , . Bookmark the permalink.

Leave a Reply