Builder Pattern vs Factory Method Pattern

Big 2 of Creational Design Pattern


15 Oct 2016 View Comments
#builder #factory #pattern

Builder? Factory? Pattern? huh?

Builder pattern is an object creational software design pattern. This pattern is often compared with “Factory” method pattern because factory method is also an object creational DP. The key difference is how the object is being created though. For example with the factory DP, createCar might return Honda or Audi. To add attributes, you will need to make additional calls such as setColor, setEngine etc on the object returned. Now with the Builder pattern, you could be specific about the object all in one statement, such as 4 all-wheel drive red Honda with v6 engine etc. Basically, factory method pattern would create an object via createCar VS Builder pattern has the ability to create an object by adding granularity to the object by applying chains of function calls to the object being created.

Here is a comparison of diagrams from the wiki for both pattern, which could give you a big picture of how they work.

With factory methods:

factory_method

With Builder pattern:

builder_pattern

I know, it’s actually hard to explain their differences just from the diagrams. So let me give you some code comparison in Java:

With factory methods:

An example is from Wikipedia that matches with the diagram above exception OrdinaryMazeGame and OrdinaryRoom are added to provide you with the picture on how multiple different instances are being created from a generic template.

public abstract class MazeGame {
    private final List<Room> rooms = new ArrayList<>();

    public MazeGame() {
        Room room1 = makeRoom();
        Room room2 = makeRoom();
        room1.connect(room2);
        rooms.add(room1);
        rooms.add(room2);
    }

    abstract protected Room makeRoom();
}

public class MagicMazeGame extends MazeGame {
    @Override
    protected Room makeRoom() {
        return new MagicRoom(); 
    }
}

public class OrdinaryMazeGame extends MazeGame {
    @Override
    protected Room makeRoom() {
        return new OrdinaryRoom(); 
    }
}

MazeGame ordinaryGame = new OrdinaryMazeGame();
MazeGame magicGame = new MagicMazeGame();

Watch closely how it makes an ordinaryGame vs magicGame objects which both will eventually inherit from MazeGame. To give you the full picture, OrdinaryMazeGame will create 2 rooms with OrdinaryRoom objects in the List<Room> rooms created by, MazeGame. Similarly MagicMazeGame will create 2 rooms with MagicRoom this time created by the parent, MazeGame. Like a real Factory, the task it does is just to construct objects.

With Builder pattern:

Builder pattern in my personal opinion is well described and explained in Effective Java (Second Ed) by Joshua Bloch. Here is the example from his book:

// Builder Pattern - Pages 14-15
package org.effectivejava.examples.chapter02.item02.builder;

public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;
    
    public static class Builder {
        // Required parameters
        private final int servingSize;
        private final int servings;
        
        // Optional parameters - initialized to default values
        private int calories = 0;
        private int fat = 0;
        private int carbohydrate = 0;
        private int sodium = 0;
        
        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }
        
        public Builder calories(int val) {
            calories = val;
            return this;
        }
        
        public Builder fat(int val) {
            fat = val;
            return this;
        }
        
        public Builder carbohydrate(int val) {
            carbohydrate = val;
            return this;
        }
        
        public Builder sodium(int val) {
            sodium = val;
            return this;
        }
        
        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }
    
    private NutritionFacts(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
    
    public static void main(String[] args) {
        NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
                .calories(100).sodium(35).carbohydrate(27).build();
    }
}

With the builder, it would be possible to do a chain-call, like new NutritionFacts.Builder(240, 8).calories... etc, which would help greatly in terms of readability. From my experience with the Builder, this is the most important factor, “readability”: they carry “names” to what/how you define the object. Let me just give you an example that will say everything about what I just said. Say you have a constructor, new Person(true, false, false, "Samsung"); vs with Builder, `new Person.Builder().hasBeard(true).isMarried(false).isDisabled(false). You know what I mean… Oh, there is another point I’d like to mention about the Builder. I recently came across a class with inheritance where I wanted to have the builder relationship. I actually ended up using “super” command. There is probably a better way to handle this in Generic but I wasn’t successful with using generics so I ended up sticking with “super” calls. Anyways, let me show you how I came across the Builder inheritance, below is just an illustration of what happened:

public class Teacher extends Employee {
    private final String name;
    public Employee(Builder builder) {
        super(builder)
        this.name = name;
    }

    public static class Builder {
        private String name;
        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Employee build() {
            return new Employee(this);
        }

        @Override
        public String toString() {
            return "Employee.Builder = " + "Employee name: " + name;
        }
    }
}

public class MathTeacher extends Teacher {
     private final String type;
     
     public Teacher(Builder builder) {
         super(builder);
         this.type = builder.type;
     }

    public static class Builder extends Employee.Builder {
        private final String type;

        public Builder(String type) {
            this.type = type;
        }

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

Then, let’s say Employee class implements Person. Now, you can apply Composite design pattern: Person p; as p=new MathTeacher.Builder("calculus").name("Jane") or p=new Teacher.Builder().name("Dan") etc… Anyways, Builder is powerful and very flexible on what and how you would like to create an object. There is only one disadvantage with the Builder. As you can see from above examples, you will end up introducing more lines of code. However, I prefer much in readability over the lines of code. Using the Builder will organize your constructor well and defined.

Share this post

Me

I am a passionate software developer working in Downtown, Vancouver. I strongly believe in art of algorithms and together with it to write clean and efficient software to build awesome products. If you would like to connect with me, choose one from below options :) You can also send me an email at