Your Guide to Design Patterns – Builder Pattern

Design Patterns Builder Pattern

This week we’ll continue our exploration of design patterns and look at the last creational pattern, the Builder pattern.

The Builder Pattern

The Gang of Four book defines the Builder pattern as follows:

“Separate the construction of a complex object from its representation so that the same construction process can create different representations.”

The Problem

We occasionally have complex objects in our system that require laborious, step-by-step initialization of many of their internal fields. The Builder pattern provides a simple process to construct such a complex object. We use it when we have a number of mandatory and optional attributes to set when constructing an object.

To initialise an object with many different attributes, we can either:

  • Construct the object with one of a number of complex constructors with a variety of attribute combinations.
  • Construct the object with one complex constructor containing all the possible attributes, many of which will not be needed all the time.
  • Construct the object with a simple constructor and call multiple setters to initialise it.

None of these solutions is particularly elegant, and they’re all error prone, because it is easy to forget to perform some of the required steps.

The Solution: Builder Pattern

To implement the Builder pattern, we refactor the object construction steps. We remove the complex construction code from its own class, and we move it into a separate builder class. This allows us to create complex objects using chained method calls (a fluent interface).

We can build a particular configuration of an object step by step, using only those steps that we really need. We use a director object to specify the required steps in the correct order. Finally, the finished product is returned from the builder class. After implementing this pattern, we won’t need to implement complex constructors with many parameters.

Steps to implement the Builder pattern:

  1. Provide a constructor for the mandatory attributes of the object.
  2. Provide setter (and getter) methods for the optional attributes.
  3. Create a static nested builder class within the class. This could also be a top-level class.
  4. Create corresponding setters methods in the builder class which return a reference to the same builder object.
  5. Provide a build() method, which returns the constructed complex object.

Builder Pattern: Example Code

While developing our first person shooter game, we’ve hit a bit of a snag. We’ve created a Combatant class with a list of attributes that keeps growing. Obviously a Combatant will have a required type. This could be a Monster, a Beast, a Zombie, a Human, whatever our creative director dreams up. But combatants will also have characteristics such as strength, speed, self-healing, intelligence, etc. They will also sustain damage, carry and wield weapons, wear armour, collect and store treasure, the list goes on. Some of these attributes will be mandatory, such as the type and intelligence, but others could be optional, using good default values.

The CombatantType could include the following values:

public enum CombatantType {
   HUMAN,
   BEAST,
   MONSTER,
   ZOMBIE;
}

The Combatant class follows:

public class Combatant {

   // mandatory attributes
   private CombatantType type;  // enum type
   private int intelligence;

   // optional attributes - using int types here for ease
   private int strength;
   private int speed;
   private int healing;
   // and more - damage, weapons, armour, treasure, etc.

   // a complex constructor with many parameters
   public Combatant(CombatantType type, int intelligence,
         int speed, int healing, int strength) {
      // appropriate code
   }

   // setters for optional attributes

   // other Combatant code...

} // end of class

Calling a complex constructor with many parameters is confusing, error prone and difficult to modify and maintain.

We could rather implement the Builder pattern by creating a static inner class inside the Combatant class, and use that to build combatants as required.

public class Combatant {

   // mandatory attributes
   private CombatantType type;  // enum type
   private int intelligence;

   // optional attributes - using int types here for ease
   private int strength;
   private int speed;
   private int healing;
   // and more - damage, weapons, armour, treasure, etc.

   // private constructor taking a Builder
   private Combatant(Builder builder) {
      this.type = builder.type;
      this.intelligence = builder.intelligence;
      this.strength = builder.strength;
      this.speed = builder.speed;
      this.healing = builder.healing;
   }

   // other Combatant code...

   @Override
   public String toString() {
      return String.format("%s [IQ=%d, strength=%d, speed=%d, healing=%d]",  
            type.toString(), intelligence, strength, speed, healing);
   } 

   // nested inner class
   public static class Builder {

      // mandatory attributes
      private CombatantType type;
      private int intelligence;

      // optional attributes with defaults
      private int strength = 10;
      private int speed = 10;
      private int healing = 0;

      // mandatory attributes
      public Builder(CombatantType type, int intelligence) {
         this.type = type;
         this.intelligence = intelligence;
      }

      // optional attributes
      public Builder strength(int strength) {
         this.strength = strength;
         return this;
      }

      public Builder speed(int speed) {
         this.speed = speed;
         return this;
      }

      public Builder healing(int healing) {
         this.healing = healing;
         return this;
      }

      public Combatant build() {
         return new Combatant(this);
      }
   }
} // end of class

This will be used as follows:

public class BuilderClient {

   public static void main(String[] args) {

      Combatant zombie = new Combatant.Builder(CombatantType.ZOMBIE, 50)
            .speed(20)
            .build();
      System.out.println(zombie);

      Combatant human = new Combatant.Builder(CombatantType.HUMAN, 120)
            .speed(80)
            .strength(80)
            .healing(20)
            .build();
      System.out.println(human);

   }
} // end of class

The builder pattern can give us a lot of flexibility in how we create objects. We can configure an object to our requirements with very little effort and in an easy to read manner.

What’s Next?

In the weeks ahead, we’ll continue examining some of the more useful design patterns. Stay tuned!

As always, please share your comments and questions.

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.