13
public class Employee {
    private String name;
    private String address;
    private int id;

    public Employee() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public String toString() {
        return "Employee [name=" + name + ", address=" + address + ", id=" + id + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}

public class Main { 
    public static void main(String[] args) {
        Employee e = new Employee();
        e.setName("Priyanka");
        Employee e1 = new Employee();
        e1.setName("Rahul");
        e1.setAddress("Delhi");
        System.out.println("Value of e :"+ e);
        System.out.println("Value of e1:"+ e1);
    }
}
Boann
  • 48,794
  • 16
  • 117
  • 146
Priyanka Taneja
  • 515
  • 1
  • 5
  • 21
  • Setters do not ensure that the item you get will be *valid*. And they cannot. A builder can. Let's say if you forget to call `employee.setId()` then you get an object with a null value for a property. While if you do `employeeBuilder.build()` you can get an exception or maybe just automatically set the ID to the next available - logic that shouldn't be in the Employee object. – VLAZ Apr 19 '19 at 09:09

3 Answers3

25

The builder pattern can be useful to:

  • apply some check on the data used to initialize the object. For example if you need a double check between variables
  • create immutable objects. You can't change an object once initialized, so you can't use setters
  • add readability of code.
  • reduce the code used to initialize the object
  • have the instance in a valid state. Using setters the object instance can be in a not valid state before all the setters are called.

Note on using the builder to create immutable objects.

When you work in a multithread environment an immutable object can be shared between threads without explicit synchronization. Because the object can't change during the time is not possible to have a race condition accessing and modifying it by two threads at the same time.

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
9

There is no need to use any pattern. You can even avoid setters with making the variables public. However,

the intent of the Builder design pattern is to separate the construction of a complex object from its representation

Source: https://en.wikipedia.org/wiki/Builder_pattern

maio290
  • 6,440
  • 1
  • 21
  • 38
  • ... and this is easier to use, as most Builder's methods return a reference to ``this`` to allow chaining of call. One could write: ``Employee jonSkeet = new Employee.Builder().withName("Jon").withLastname("Skeet").withSalary(1_000_000).build()`` – spi Apr 18 '19 at 15:08
  • @spi It makes code so much more easy to read and debug. Is this the only reason to use builder design pattern? – Priyanka Taneja Apr 18 '19 at 15:15
  • @PriyankaTaneja the only one no... You can also build several "Jon Skeet" just calling ``build()`` several times. Again, this may seem a minor advantage, but these little things put together makes a great difference between easy code and spaghetti code. – spi Apr 18 '19 at 15:17
  • Imagine that you had a main constructor with 10 arguments (a bad idea to start) and the fields were set with defaults. Instead of having multiple constructors for setting only certain values, you can use the Builder design pattern to set various values without confusion, while retaining the defaults for the other values. – WJS Apr 18 '19 at 15:32
5

Using a builder pattern has a few advantages:

  1. Unlike with setters (which make your class mutable), a builder can be used to contruct immutable objects. In many cases immutable objects are preferred over mutable objects, because they are easier to understand and maintain, and because they avoid the need for locking in multithreaded environments.

  2. A builder can make sure that the object satisfies some invariants even directly after construction. For example, if your class has a name field which must never be null, the builder can check this condition and fail to construct the object when not satisfied.

Both things you can also accomplish by using a constructor which takes all the class contents as parameters, but that will be quite unreadable when your class has more than a few fields to initialize.

Hoopje
  • 12,677
  • 8
  • 34
  • 50