venerdì 25 settembre 2015

Static Factory Method in Java

In this post we explain how to encapsulate an entity into an object using the Static Factory Method in the Java language. Consider the scenario where you need to create a class to wrap a Java developer, the JavaDeveloper class contains the following fields:


Only name is mandatory, while salary, company, email and phone are optional. There are several ways to implement the JavaDeveloper class, but since we have one mandatory field and several optional fields, the static factory method is probably a good choice for our. So we can create the following class to implement the pattern:

public class JavaDeveloper {

   // required field
   private String name;

   // optional fields
   private Double salary;
   private String company;
   private String email;
   private String phone;

   // private constructor
   private JavaDeveloper(final String name) {
      this.name = name;
   }

   // static factory method
   public static JavaDeveloper create(final String name) {
      if (name == null) {
         throw new IllegalArgumentException("missing mandatory field");
      }

      return new JavaDeveloper(name);
   }

   // getters
   public String getName() {
      return name;
   }

   public Double getSalary() {
      return salary;
   }

   public String getCompany() {
      return company;
   }

   public String getEmail() {
      return email;
   }

   public String getPhone() {
      return phone;
   }

   // setters
   public JavaDeveloper setSalary(final Double salary) {
      this.salary = salary;
      return this;
   }

   public JavaDeveloper setCompany(final String company) {
      this.company = company;
      return this;
   }

   public JavaDeveloper setEmail(final String email) {
      this.email = email;
      return this;
   }

   public JavaDeveloper setPhone(final String phone) {
      this.phone = phone;
      return this;
   }
}

As you can see there is a private constructor, so the user can create an instance only with the factory method, passing the mandatory parameter. Getters are defined according to the JavaBeans specifications, while setters return the instance reference. In addition the instance returned from create can invoke directly a method, so you can easily set the optional fields using the method chaining:

JavaDeveloper dev = JavaDeveloper.create("Coyote")
                                 .setCompany("ACME")
                                 .setPhone("1234");

The disadvantage of this pattern is the impossibility to inherit the class developed, as only classes with public or protected constructors can be subclassed, so it's up to you to decide if this approach can be applied in your code.