Friday, August 17, 2012

NetBeans 7.2: Refactoring Constructor As Static Factory

In the post NetBeans 7.2: Refactoring Parameterized Constructor As Builder, I looked at how NetBeans 7.2 supports refactoring a constructor to a builder as described in Item 2 of the Second Edition of Effective Java. In this post, I look at how NetBeans 7.2 similarly supports refactoring constructors to factories as described in Item #1 of Effective Java.

I start with an Employee class that is largely the same as the one I used in my previous post on refactoring a constructor to a builder. There are some minor differences, the most significant being that the attributes of the version used here cannot be final as the factory initializer approach does not allow final class attributes because they are not set in the constructor with this approach.

Employee.java with Traditional Constructor
package dustin.examples;

/**
 * Simple employee class intended to illustrate NetBeans 7.2 and refactoring
 * constructor to use Factory initializer as discussed in Item #1 of Joshua
 * Bloch's <em>Effective Java</em>.
 * 
 * @author Dustin
 */
public class Employee 
{
   private String lastName;

   private String middleName;

   private String firstName;

   private long id;

   private int birthYear;

   private int birthMonth;

   private int birthDate;

   private int hireYear;

   private int hireMonth;

   private int hireDate;

   public Employee(
      final String newLastName,
      final String newMiddleName,
      final String newFirstName,
      final long newId,
      final int newBirthYear,
      final int newBirthMonth,
      final int newBirthDate,
      final int newHireYear,
      final int newHireMonth,
      final int newHireDate)
   {
      this.lastName = newLastName;
      this.middleName = newMiddleName;
      this.firstName = newFirstName;
      this.id = newId;
      this.birthYear = newBirthYear;
      this.birthMonth = newBirthMonth;
      this.birthDate = newBirthDate;
      this.hireYear = newHireYear;
      this.hireMonth = newHireMonth;
      this.hireDate = newHireDate;
   }

   @Override
   public String toString()
   {
      return  this.firstName + " " + this.middleName + " " + this.lastName
            + " with ID " + this.id;
   }
}

Right-clicking on the constructor of this class leads to the choices for refactoring including the highlighted choice to "Replace Constructor with Factory..."

When the "Refactor: Replace Constructor with Factory..." choice is selected, a window like that shown in the next screen snapshot appears. It has the name "create" for the factory method by default.

One of the advantages of these static initialization factories over constructors is the ability to name them as we like rather than always needing to use the class name. This can lead to them being more expressive and means potentially less reliance on overloading. The next screen snapshot shows my change of the name of the method to be generated.

When the above options are chosen, the class's source code is automatically changed to the code shown in the next code listing. Note that the constructor is changed from public to private and a new newInstance method is generated.

Refactored Employee.java (with White Space Adjustments Made Manually)
package dustin.examples;

/**
 * Simple employee class intended to illustrate NetBeans 7.2 and refactoring
 * constructor to use Factory initializer as discussed in Item #1 of Joshua
 * Bloch's <em>Effective Java</em>.
 * 
 * @author Dustin
 */
public class Employee 
{
   public static Employee newInstance(
      final String newLastName, final String newMiddleName,
      final String newFirstName, final long newId,
      final int newBirthYear, final int newBirthMonth,
      final int newBirthDate, final int newHireYear,
      final int newHireMonth, final int newHireDate)
   {
      return new Employee(newLastName, newMiddleName, newFirstName,
                          newId, newBirthYear, newBirthMonth, newBirthDate,
                          newHireYear, newHireMonth, newHireDate);
   }
   private final String lastName;

   private final String middleName;

   private final String firstName;

   private final long id;

   private final int birthYear;

   private final int birthMonth;

   private final int birthDate;

   private final int hireYear;

   private final int hireMonth;

   private final int hireDate;

   private Employee(
      final String newLastName,
      final String newMiddleName,
      final String newFirstName,
      final long newId,
      final int newBirthYear,
      final int newBirthMonth,
      final int newBirthDate,
      final int newHireYear,
      final int newHireMonth,
      final int newHireDate)
   {
      this.lastName = newLastName;
      this.middleName = newMiddleName;
      this.firstName = newFirstName;
      this.id = newId;
      this.birthYear = newBirthYear;
      this.birthMonth = newBirthMonth;
      this.birthDate = newBirthDate;
      this.hireYear = newHireYear;
      this.hireMonth = newHireMonth;
      this.hireDate = newHireDate;
   }

   @Override
   public String toString()
   {
      return  this.firstName + " " + this.middleName + " " + this.lastName
            + " with ID " + this.id;
   }
}

There are multiple advantages to using static initialization factory methods rather than constructors. These include the ability to provide different and more meaningful names that do not necessarily require overloading because they can be different. I like to name these methods in such a way that some of their parameters are implied, resulting in the need to provide fewer arguments to that method than would be necessary for a constructor.

Other advantages of the static factory approach of acquiring an instance and two disadvantages of this approach are discussed in Item #1 of Effective Java. That item concludes, "Often static factories are preferable, so avoid the reflex to provide public constructors without first considering static factories." NetBeans 7.2 makes it easy to see how a constructor can be refactored into a static factory and will even do the basic work for the developer.

1 comment:

Anonymous said...

Hi Dustin,

My name is Tina, and I’m the community manager for Atomic Reach, a content curation platform that connects bloggers with brands looking for high-quality content. I am reaching out to you about an opportunity to be featured on http://bandofcoders.com.

Atomic Reach is working with Band of Coders to invite a select group of bloggers to join the Band of Coders community. We’re looking for blogs on topics such as software development, web development, and lean development.

What’s in it for you? The Band of Coders editorial team will only publish an excerpt and link to your posts so they’ll be sending new readers to your blog. It’s also a new way to interact with and reach new people, and boost your blog’s search engine ranking.

Social Media Love for you too! Beyond having your content featured on the Band of Coder’s site, they will also be promoting your content via Facebook, Twitter, Google+, Pinterest and Tumblr!

If you’re interested, please send me an email at tinajin @atomicreach.com with “Coders” in the subject line, and I’ll send you a link to activate your account. I’d also be happy to answer any questions.

We look forward to you joining the Band of Coders community.

Sincerely,
Tina Jin
Community Manager