The Fluent Builder as Solution to the Builder Pattern and Inheritance

What a title! If you do not know what the builder pattern is, you can look at my post here. A builder can be helpful, but you quickly realize it is painful to handle this pattern with inheritance.

Let’s use this simple example: we want to create classes representing a SUV and a coupe.

public class Car { 

    private Color color;
    private Engine engine;

}

public class SUV extends Car { 

   private FourWheelDriveSystem wdSystem;

}

public class Coupe extends Car {  

   private Door[] twoDoors;

}

We want to use the builder pattern to instantiate SUV and Coupe objects. We could simply duplicate the code from the Car Builder in SUV and Coupe. It may be ok if there are not many properties. But if we want to avoid duplicating, we can create a Car, SUV and Coupe Builders:

public class Car {

  private Color color;
  private Engine engine;

  public static class Builder { // see post on builder pattern for more details
     private Color color;
     private Engine engine;

     public Builder withColor(Color color) { ... }
     public Builder withEngine(Engine engine) { ... }
     public Car build() { ... } 
  }

}

public class SUV extends Car {

   private FourWheelDriveSystem wdSystem;

   public static class Builder extends Car.Builder { 
     private FourWheelDriveSystem wdSystem;

     public Builder withWdSystem(FourWheelDriveSystem wdSystem) { ... }
     public SUV build() { ... }
   }
}

public class Coupe extends Car {

   private DoorSystem twoDoors;

   public static class Builder extends Car.Builder {
      private DoorSystem twoDoors;

      public Builder withTwoDoors(DoorSystem twoDoors) { ... }
      public Coupe build() { ... }
   }

}

So far so good. However, this code fails:

new SUV.Builder()
  .withColor(color) // returns a Car.Builder
  .withWdSystem(wdSystem) // do not compile because the function belongs to SUV.Builder
  .withEngine(engine)
  .build(); // would return a Car object, not a SUV...

One solution is to use Recursive Generics:

// in Car class
public static class Builder<SELF extends Car.Builder<SELF>> {

  public SELF withColor(Color color) { 
    this.color = color;
    return (SELF) this;
  }
  ...
}

// in SUV class
public static class Builder extends Car.Builder<Builder> {

  public Builder withWdSystem(FourWheelDriveSystem wdSystem) { 
     this.wdSystem = wdSystem;
     return this;
  }

}

Now the code works:

new SUV.Builder()
   .withColor(color) // now returns a SUV.Builder
   .withWdSystem(wdSystem) 
   .withEngine(engine)
   .build(); // would return a SUV object

Et voila! But it takes a bit of brain power to understand for a programmer who has not developed the code to understand what the builder does…

Author: Toujon Lyfoung

This paragraph is supposed to be the place where I put my credentials and achievements. In my opinion, degrees and jobs do not tell much about a person. If you want to know me, read my posts! Blogging has been fun. I do not pretend to do much. I am simply processing, tracking and sharing my reflection. Comments are definitely welcomed to help me continue in my learning.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s