While “Design patterns” do make developers’ life easier, they usually are not always perfect. I was recently developing a custom view library, for which I was looking into the Builder design pattern. But I required a customized Builder class which forces users to invoke some parameters, while allowing multiple non-optional setter invocations(Good ol’ Builder) That’s what Fluent Builder is. Here is a code snippet for the same:

GraphData gd = GraphData.builder(this)

.setPointMap(pointMap)

.setGraphStroke(R.color.Black)

.setGraphGradient(R.color.BlueViolet, R.color.RoyalBlue)

.setStraightLine(true)

.setPointRadius(10)

.setPointColor(R.color.Red)

.animateLine(true)

.build();

Now we’ve all seen this before, you may ask what’s so Fluent about it? Let’s recap what Builder design pattern exactly is

Definition of Builder Pattern according to Wikipedia

The Builder design pattern intends to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations.

You may ask what’s the difference between the builder pattern you’ve been using all along and this new Fluent Builder Pattern?

Forced invocation of required methods

If you look closely after you trigger the GraphData.builder(this) method, you’re only presented with one auto-complete suggestion i.e. .setPointMap(PointMap pm) and after setting the point map you’re required to invoke the .setGraphStroke(int colorRes) method, so on and so forth. This type of chained method invocation is what the Fluent Builder Design Pattern entails.

This type of chained invocation solves an inherent problem with the Builder pattern. When the developer misses out on some setter methods that needed to be invoked to initialize some crucial objects which may end up causing some aberrant runtime exceptions.

For this problem, you can now choose to implement the Fluent Builder Design pattern, which eliminates the chances of the developer errors, along with all the code goodness that comes along with this design pattern.

Let’s get into the nitty-gritty implementation details!

Let’s declare some interfaces which will help us achieve the same.

public interface IGraphData {

IGraphStroke setPointMap(PointMap graphPoints);

} public interface IGraphStroke {

Builder setGraphStroke(int colorRes);

}

The IGraphData and IGraphStroke interfaces will be implemented by the Builder class, and we can put our constructional logic in the overridden methods.

These interfaces are designed to chain the invocation logic for the Builder,

the interface method of IGraphData has the return type of IGraphStroke, and the return type of this interface method is Builder, which essentially is a gateway to all the other optional setter methods present within the Builder class.

We need to provide the Instance method to our Builder class and keep all the constructors private, this instance method should have the expected return type of the first forced invocation.

public static IGraphData builder(Context context) {

return new Builder(context);

}

Viola!!

It’s that simple. If you’d like to look at the entire Builder code for GraphData present in CurveGraphView, you can find it here: GitHub.