When to use a builder design pattern? real life tips
Interview questions relating to design patterns are very popular in job interviews. Even if this topic is not covered in rare occassions, you can bring it up yourself to open-ended questions to impress your interviewers.
Q. What are the key difference(s) between a factory and a builder design patterns?
A. The builder design pattern builds an object over several steps. It holds the needed state for the target item at each intermediate step. The StringBuilder is a good example that goes through to produce a final string. Here is a real world example that shows how builders are used instead of constructors to create Immutable objects. Creating immutable objects where applicable is a development best practice.
The factory design pattern describes an object that knows how to create several different but related kinds of object in one step, where the specific type is chosen based on given parameters.
Q. When would you use a builder design pattern?
A.
- To construct a complex object. For example, to construct XML DOM objects and any other hierachichal objects. You have to create plenty of nodes and attributes to get your final object.
- Builder pattern makes your code more readable as explained in the article "Using Builders instead of Constructors to create Immutable objects". The article explains how you can create immutable objects in Java by using the builder design pattern as opposed to using multiple constructors, which is known as the "telescoping constructor anti pattern".Firstly, let's see what is not so elegant about using a constructor as shown below with a CashBalance object that takes 3 BigDecimal arguments. Then we will see how a builder class will make your code more intuitive.
Q. Can you give some examples from your experience?
A.
Example 1: Custom class.
package com.myapp.data; import java.math.BigDecimal; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.springframework.util.Assert; public class NetAsset { public static NetAsset EMPTY = new Builder().setGrossAssetValueBeforeTax(BigDecimal.ZERO) .setGrossAssetValueAfterTax(BigDecimal.ZERO).setTotalAssets(BigDecimal.ZERO) .setTotalInvestments(BigDecimal.ZERO) .setTotalLiabilities(BigDecimal.ZERO) .setTotalReceivables(BigDecimal.ZERO) .build(); private final BigDecimal grossAssetValueAfterTax; private final BigDecimal grossAssetValueBeforeTax; private final BigDecimal totalReceivables; private final BigDecimal totalInvestments; private final BigDecimal totalAssets; private final BigDecimal totalLiabilities; // add more private NetAsset(Builder builder) { Assert.notNull(builder.grossAssetValueAfterTax); Assert.notNull(builder.grossAssetValueBeforeTax); Assert.notNull(builder.totalReceivables); Assert.notNull(builder.totalInvestments); Assert.notNull(builder.totalAssets); Assert.notNull(builder.totalLiabilities); this.grossAssetValueAfterTax = builder.grossAssetValueAfterTax; this.grossAssetValueBeforeTax = builder.grossAssetValueBeforeTax; this.totalReceivables = builder.totalReceivables; this.totalInvestments = builder.totalInvestments; this.totalAssets = builder.totalAssets; this.totalLiabilities = builder.totalLiabilities; } public BigDecimal getGrossAssetValueAfterTax() { return grossAssetValueAfterTax; } public BigDecimal getGrossAssetValueBeforeTax() { return grossAssetValueBeforeTax; } public BigDecimal getTotalReceivables() { return totalReceivables; } public BigDecimal getTotalInvestments() { return totalInvestments; } public BigDecimal getTotalAssets() { return totalAssets; } public BigDecimal getTotalLiabilities() { return totalLiabilities; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } //inner builder class public static class Builder { private BigDecimal grossAssetValueAfterTax; private BigDecimal grossAssetValueBeforeTax; private BigDecimal totalReceivables; private BigDecimal totalInvestments; private BigDecimal totalAssets; private BigDecimal totalLiabilities; // add more public Builder setGrossAssetValueAfterTax(BigDecimal grossAssetValueAfterTax) { this.grossAssetValueAfterTax = grossAssetValueAfterTax; return this; } public Builder setGrossAssetValueBeforeTax(BigDecimal grossAssetValueBeforeTax) { this.grossAssetValueBeforeTax = grossAssetValueBeforeTax; return this; } public Builder setTotalReceivables(BigDecimal totalReceivables) { this.totalReceivables = totalReceivables; return this; } public Builder setTotalInvestments(BigDecimal totalInvestments) { this.totalInvestments = totalInvestments; return this; } public Builder setTotalAssets(BigDecimal totalAssets) { this.totalAssets = totalAssets; return this; } public Builder setTotalLiabilities(BigDecimal totalLiabilities) { this.totalLiabilities = totalLiabilities; return this; } public NetAsset build() { return new NetAsset(this); } } }
To use this class
NetAsset.Builder builder = new NetAsset.Builder(); builder.setGrossAssetValueBeforeTax(BigDecimal.valueOf("3500.00")) .setGrossAssetValueAfterTax(BigDecimal.valueOf("500.00")) .setTotalAssets(BigDecimal.valueOf("3500.00")) .setTotalReceivables(BigDecimal.valueOf("2500.00"));
or
return NetAsset.EMPTY;
Example 2: The Mock objects library classes.
m.expects(once()) .method("method1") .with(eq(1), eq(2)) .returns("someResponse");
Example 3: The StringBuilder class.
return new StringBuilder("initial text") .append("more text") .append("some more text").toString();
Example 4: Apache Camel route builders.
private void configureJobSweeperRoute() { from(TIMER_START_UP) .routeId("JobRecovery") .delay(RECOVERY_JOB_KICKIN_DELAY) .log(INFO, "Start checking incompleted jobs on start up") .bean(recoveryService, "startUpJobRecovery") .end(); }
So, it is very widely used.
Other design patterns - real life examples
- Sharing and reusing objects with the flyweight design pattern in Java
- Deadlock Retry with JDK Dynamic Proxy
- Proxy design pattern implementing thread safe wrappers
- Java I/O -- the Decorator and proxy design pattern interview questions and answers
- Java design pattern interview questions and answers: strategy and factory pattern
- Sharing and reusing objects with the flyweight design pattern in Java
- Observer design pattern for publish/Subscribe model
Labels: design pattern
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home