«^»
11. The factory pattern

Although this programming style encourages the client to use the interface rather than the class, the client is still using the class if it has to create an instance of the class:

Date tDate = new DateImpl(2000, 12, 25);

Suppose we now need to represent people and the constructor for the class PersonImpl needs to create a DateImpl object for a person's date of birth:

public PersonImpl(String pName, int pYear, int pMonth, int pDay)
{
   iName = pName;
   iDateOfBirth = new DateImpl(pYear, pMonth, pDay);
}

Including this code in PersonImpl means that it is dependent on DateImpl. If we make a change to the DateImpl class, we will need to recompile (and re-test) PersonImpl (as well as DateImpl).

There is one other problem. Suppose we now wish to switch to using some other class that implements the Date interface. We need to detect all the occurrences of:

new DateImpl( ... )

and change them to create instances of the new class. One of the principles of software engineering is that the commitment to some decision should be made in one place and not all over the place.

One way to do this which also overcomes the recompilation problem is to use the factory pattern (as described in [9]). We can introduce an interface (e.g., Factory) and a class (e.g., FactoryImpl) that are responsible for creating objects. They could have a method called createDate:

public Date createDate(final int pYear, final int pMonth, final int pDay)
{
   return new DateImpl(pYear, pMonth, pDay);
}

Clients should be written in terms of this method. For example, PersonImpl's constructor contains:

iDateOfBirth = new DateImpl(pYear, pMonth, pDay);

This should be replaced by:

iDateOfBirth = iFactory.createDate(pYear, pMonth, pDay);

where iFactory is a variable of the interface type Factory.

If the FactoryImpl object is created in the program's program class, then only the program class, FactoryImpl and DateImpl will need to be recompiled if the code of the DateImpl class needs to be changed. Or, if FactoryImpl chooses to use some class other than DateImpl, then only the program class and FactoryImpl will need to be recompiled.