Design Patterns in Android – Builder
Design patterns are reusable solutions to the most commonly occurring software problems. Let’s take a look at the Builder pattern in Android!
Design patterns are reusable solutions to the most commonly occurring software problems. They can speed up the development process by providing a proven way of resolving frequent issues. Discover Builder, which is one of the most common design patterns, and check out some examples of Android implementations in practice!
Introduction
Design patterns can be divided into three sections:
- Creational Design Patterns deliver solutions for creating classes and objects (Singleton, Factory, Builder, etc.)
- Structural Design Patterns relate to the arrangement of classes and objects (e.g. Composite, Facade, Adapter)
- Behavioral Design Patterns give us ways to communicate between objects and classes (Command, Observer, Strategy, etc.)
Builder
The Builder pattern simplifies object creation in a very clean and readable way. It’s very helpful when we have some model classes with many parameters. We can make some of them optional, or required, and we don’t force the user to use a specific order (as found in the constructor). By using this Builder pattern, the result is an elegant chain of methods.
The most common use can be found in the AlertDialog.Builder() class:
1 2 3 4 | new AlertDialog.Builder(this) .setTitle("Design Patterns") .setMessage("Builder is awesome") .create(); |
How can we create the Builder class for our own usage?
Builder in practice
Let’s assume we have some model class for the user:
1 2 3 4 5 | public class User { private String firstName; private String lastName; private int age; } |
So, instead of creating objects of this class using constructors, we want to create them using a Builder pattern like this:
1 2 3 4 5 | new User.Builder() .setFirstName("Leonardo") .setLastName("da Vinci") .setAge(67) .create(); |
How can we do this? First of all, we need to create a static Builder
class inside the User class, which will have the methods to build our object. The key to having chaining methods is ensuring that the builder methods return a Builder
class. Look at the example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | static class Builder { private String firstName; private String lastName; private int age; public Builder setFirstName(final String firstName) { this.firstName = firstName; return this; } public Builder setLastName(final String lastName) { this.lastName = lastName; return this; } public Builder setAge(final int age) { this.age = age; return this; } public User create() { return new User(this); } } |
For every parameter, we have a setter – the difference is that those methods return a Builder type. At the end, we have a method which uses a constructor from the User
class and returns a User
type – this is the part where our mess is kept hidden.
NEED A SUCCESSFUL TEAM?
We’re 100% office based team with 7-years’ experience
in mobile & web app development
Then, we need to create constructor with all the parameters in model class
User
: 1 2 3 4 5 6 7 8 9 10 11 | public class User { private String firstName; private String lastName; private int age; private User(final Builder builder) { firstName = builder.firstName; lastName = builder.lastName; age = builder.age; } } |
The important thing here is that the
User
constructor is private, so it can’t be accessed from the other class and we must use Builder
to create a new object. Of course, we can make some of the parameters required (as for now, all are optional) by modifying our create()
method and throwing some exceptions, e.g.:
1 2 3 4 5 6 7 | public User create() { User user = new User(firstName, lastName, age); if (user.firstName.isEmpty()) { throw new IllegalStateException("First name can not be empty!"); } return user; } |
That’s it. Through this, we have created our User.Builder()
class!
Builder – one pro-tip
If you were patient enough to get through the whole blog post, I have one tip for you regarding Builder patterns: you can generate the whole Builder class using IntelliJ!
All you need to do is place the caret on the constructor in your class and choose Refactor-> Replace Constructor with Builder in the context menu. The Builder class, complete with all the methods, will be auto generated and ready for use.
You can read more here: IntelliJ: Replace Constructor with Builder
Conclusion
Builder pattern is a great approach, not only for model classes but for every object which has more than three or four parameters. With a bit of additional work, we can increase the readability of our code. Design patterns are recognized as the best practice, so it’s big advantage if you know some of them and Builder is a good one to start with.
About the author
Ready to take your business to the next level with a digital product?
We'll be with you every step of the way, from idea to launch and beyond!
Great examples, thanks Paulina!
In case of Android programming and its first-class citizen language – Kotlin it’s good to notice that Builder pattern can be easily replaced by named parameters and default values in methods’ signatures 🙂
Thnx Paulina, this a really great blog. Most examples are either overwhelmed or they have those simple non realistic examples like building a pizza. Picasso is also a great real world example.