DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
What's in store for DevOps in 2023? Hear from the experts in our "DZone 2023 Preview: DevOps Edition" on Fri, Jan 27!
Save your seat
  1. DZone
  2. Coding
  3. Languages
  4. Achieving Immutability with Builder Design Pattern

Achieving Immutability with Builder Design Pattern

Immutable classes define objects which, once created, never change their state.

Shekhar Gulati user avatar by
Shekhar Gulati
·
Aug. 03, 10 · Tutorial
Like (2)
Save
Tweet
Share
61.41K Views

Join the DZone community and get the full member experience.

Join For Free

One piece of advice from Effective Java is that you should make your classes Immutable unless there is a good reason to make them mutable. If a class cannot be made immutable, limit its mutability as much as possible. Immutable classes define objects which, once created, never change their state. All the state information is provided at the time the object is constructed and it does not change for the lifetime of the object.

Why should we write Immutable classes?

Immutable classes offer many advantages over mutable classes. These are:

  1. An immutable object is simple and easier to use as it can be in only one state, the state in which it was created.
  2. They are inherently thread safe, i.e. they do not require synchronization.
  3. The objects of immutable classes can be shared freely. For example, Boolean class reuses its existing instances TRUE and FALSE and whenever you call Boolean.valueOf method it gives you the already created instances.

Creating an Immutable class

A simple immutable class can be like this:

public final class User {private final String username;private final String password;public User(String username, String password) {this.username = username;this.password = password;}public String getUsername() {return username;}public String getPassword() {return password;}}

 

This class is immutable because:

  1. It does not provide setter methods or mutators.
  2. The Class can't be extended because it is final. This could have also been done by making the constructor private.
  3. Fields of the class are all final and private.

It is important to note that this class was very simple with only two fields.  In most of the classes in our real applications there are more than two fields. Also, most of these fields are not mandatory for object creation. For example, a user in a real application will have a username, password, firstname, lastname, creationDate, emailAddress, etc., but for user creation here, only a username and password are required. So, we design our class as shown below:

public final class User {private final String username;private final String password;private String firstname;private String lastname;private String email;private Date creationDate;public User(String username, String password) {this.username = username;this.password = password;creationDate = new Date();}public String getUsername() {return username;}public String getPassword() {return password;}public String getFirstname() {return firstname;}public void setFirstname(String firstname) {this.firstname = firstname;}public String getLastname() {return lastname;}public void setLastname(String lastname) {this.lastname = lastname;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Date getCreationDate() {return new Date(creationDate.getTime());}}

 

This class is not immutable because it has mutators, i.e. setters. So, instances of this class can be modified after creation.  This approach has the disadvantage that objects can be in an inconsistent state part of the way through their construction and you have to put in extra effort to ensure thread safety.

Builder Design Pattern comes to the Rescue

According to Gof:

The Builder Pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.

The builder design pattern provides a way for you to build complex immutable objects. The process is:

  1. The client calls a constructor (or static factory) with all the required parameters and gets a builder object.
  2. The client calls setter like methods to set each optional parameter of interest.
  3. Finally the client calls the build method to generate the object which is immutable.

Immutable User

public class ImmutableUser {private final String username;private final String password;private final String firstname;private final String lastname;private final String email;private final Date creationDate;private ImmutableUser(UserBuilder builder) {this.username = builder.username;this.password = builder.password;this.creationDate = builder.creationDate;this.firstname = builder.firstname;this.lastname = builder.lastname;this.email = builder.email;}public static class UserBuilder {private final String username;private final String password;private final Date creationDate;private String firstname;private String lastname;private String email;public UserBuilder(String username, String password) {this.username = username;this.password = password;this.creationDate = new Date();}public UserBuilder firstName(String firsname) {this.firstname = firsname;return this;}public UserBuilder lastName(String lastname) {this.lastname = lastname;return this;}public UserBuilder email(String email) {this.email = email;return this;}public ImmutableUser build() {return new ImmutableUser(this);}}public String getUsername() {return username;}public String getPassword() {return password;}public String getFirstname() {return firstname;}public String getLastname() {return lastname;}public String getEmail() {return email;}public Date getCreationDate() {return new Date(creationDate.getTime());}}

 

You should also check the invariants in the build method and throw in an IllegalStateException if any attribute is invalid. This will ensure that the object is in a workable state once it is instantiated.

The client code will look like this :

public static void main(String[] args) {ImmutableUser user = new ImmutableUser.UserBuilder("shekhar","password").firstName("shekhar").lastName("gulati").email("shekhargulati84@gmail.com").build();}

 

In this way you build a complex object which is immutable and has all the advantages of immutable objects.

Note : Effective Java is a must read for every Java developer

Design Object (computer science)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Simulating and Troubleshooting StackOverflowError in Kotlin
  • NEXT.JS 13: Be Dynamic Without Limits
  • Why It Is Important To Have an Ownership as a DevOps Engineer
  • How to Perform Accessibility Testing of Websites and Web Apps

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: