Constructing Builder Set Methods in Java
Articles —> Constructing Builder Set Methods in Java
There are occasions in programming when one must build a very complex class, whose construction is dependent upon a great number of parameters - parameters which vary in both value and number. Typical techniques for building these objects rely on complex constructors, a great number of 'setter' methods, or a combination of both.
As an example, we can create a class that represents something we often build in real life - Pizza. The code that follows contains the information we want to specify for our pizza - it allows us to specify the toppings, if we want it delivered, etc...This is a simple class, all of its variables are private and accessed only through the modifier get/set methods. For brevity I have left out comments in the code.
import java.util.ArrayList; import java.util.List; public class Pizza{ private String crustType = "Thick"; private boolean extraCheese = false; private boolean forDelivery = false; private List<String> toppings = new ArrayList<String>(); public Pizza(){ } public Pizza(String crust, boolean extraCheese, boolean forDelivery, String...toppings){ this.crustType = crust; this.extraCheese = extraCheese; this.forDelivery = forDelivery; for ( String t : toppings ){ this.topings.add(t); } } public String getCrustType() { return crustType; } public void setCrustType(String crustType) { this.crustType = crustType; } public boolean isExtraCheese() { return extraCheese; } public void setExtraCheese(boolean extraCheese) { this.extraCheese = extraCheese; } public boolean isForDelivery() { return forDelivery; } public void setForDelivery(boolean forDelivery) { this.forDelivery = forDelivery; } public List<String> getToppings() { return toppings; } public void addTopping(String topping) { this.toppings.add(topping); } }
To use this class, we need to make use of the constructor, or use the empty argument version and go through several lines of setter methods.
//use the full constructor Pizza pizza = new Pizza("Thick", false, false, "peppers", "olives"); //Or build using accessor methods... pizza = new Pizza(); pizza.setCrustType("Thick"); pizza.setExtraCheese(false); pizza.setForDelivery(false); pizza.addTopping("peppers"); pizza.addTopping("olives");
Note with varying types of information, providing as many constructors as there are parameters can become cumbersome, and accessing each setter method can get lengthy and excessive. We can however slightly adjust the source code of our class, modifying the setter methods. Take a look at the code below - the same pizza class with a few modifications. Notice anything different?
import java.util.ArrayList; import java.util.List; public class Pizza{ private String crustType = "Thick"; private boolean extraCheese = false; private boolean forDelivery = false; private List<String> toppings = new ArrayList<String>(); public Pizza(){ } public Pizza(String crust, boolean extraCheese, boolean forDelivery, String...toppings){ this.crustType = crust; this.extraCheese = extraCheese; this.forDelivery = forDelivery; for ( String t : toppings ){ this.toppings.add(t); } } public String getCrustType() { return crustType; } public Pizza setCrustType(String crustType) { this.crustType = crustType; return this; } public boolean isExtraCheese() { return extraCheese; } public Pizza setExtraCheese(boolean extraCheese) { this.extraCheese = extraCheese; return this; } public boolean isForDelivery() { return forDelivery; } public Pizza setForDelivery(boolean forDelivery) { this.forDelivery = forDelivery; return this; } public List<String> getToppings() { return topings; } public Pizza addTopping(String toping) { this.topings.add(toping); return this; } }
The instance (this) is returned for every setter method. This might seem strange relative to what is commonly taught (setter methods are void), so what does this accomplish? Coming back to our first example where we construct an instance of this class - both previous ways still work, so we do not break any code relying on the techniques. But the new modifications allow us to build a pizza with an entirely new syntax, nesting the setter methods as needed:
//Now we have another way to build a pizza Pizza pizza = new Pizza().setCrustType("Thick").setExtraCheese(false).setForDelivery(false).addToping("peppers").addToping("olives");
This may seem like a strange syntax, but can add a more compact and dynamic alternative to building a class. It still can be cumbersome to build instance of complex classes, but rather than relying on a complex number of constructors, or a large number of sequential setter method calls, we can build a class in a single line of code. Note that often, given the complexity of building certain objects, abstracting the building process can be beneficial using the Builder Pattern
This article is an adaptation to an article I wrote in the Java Programming ForumsThere are no comments on this article.