Factory Method Pattern
 

- JavaTouch

- Design Patterns Home
- Singleton Pattern
- Inversion of Control (IoC) Pattern

Factory Method

Defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiate to subclasses.

Type - Creational


 

Related design concepts

- Code should be open for extension but closed for for modification.
- Depend upon abstraction. Do not depend upon concrete classes
- Encapsulate things that very

Recommended Book
This Tutorial is based on contents on Head First Design Patterns. The Best book on Design Patterns that teaches Design Patterns in brain friendlier way. 


More Links on Factory Method

- Factory Method Pattern at Wiki

- Factory Method Pattern (at DoFactory.com)

- Factory Method in Brief (at Earthlink)

 - The Factory Pattern (at java.net)

- A tutorial on Factory Method (from JavaWorld)

- A brief summary

 

By the By

Factories are useful when you need to separate the entities that create objects from the type of objects being created. They are useful for satisfying the DIP, when the DIP violation is causing you pain. On the other hand, factories can be a pain in the butt. After all, what could be simpler than new LinkedList()? So take care not to leap into factories without good reason. Don't use them by default, and don't start using them at the first hint that they might be useful. Wait until you have a concrete problem that factories will solve. And then, don't hesitate to use them.
- Robert C Martin
(Ref: java.net )

 

Enough on serious designing and Java, What about cup of tea?

- Facts of Tea

- Online Tea Shop

Rationale

- Instantiation is an activity that should not always be done in public and often lead to coupling problems.

- Whats wrong with new?
      Technically there is nothing wrong with new, after all its a fundamental part of Java. The real culprit is 'CHANGE' (open close principle) and how change impact our use of new.

Example:

Lets say you'r system support a tea shop serving tea. Here is your class;

public class TeaShop {

   public Tea orderTea(String type) {
        Tea tea = null;

        if (type == "white") {
            tea = new WhiteTea();
        } else if (type == "green") {
            tea = new GreenTea();
        } else if (type == "black") {
            tea = new BlackTea();
    }

    tea.prepare();
    tea.addFlavour();
    tea.decorate();

    return tea;
    }
}
 
Teashop decides to introduce another type of tea called Herbal tea !

Now are you going to change the orderTea method as follows;

        if (type == "white") {
            tea = new WhiteTea();
        } else if (type == "green") {
            tea = new GreenTea();
        } else if (type == "black") {
            tea = new BlackTea();
        } else if (type == "herbal") {
            tea = new HerbalTea();

OK this serves your purpose. BUT you have broken the open close principle and every time a new type of tea is introduced, you are going to change the orderTea method !!!

 

Solution Path - Encapsulating Object Creation

Take the object creation code and move it out into another object that is only going to be concerned with making tea. We will call this new object a factory.

publicclass SimpleTeaFactory {

    public Tea makeTea(String type) {

        Tea tea = null;
        if (type == "white") {
            tea = new WhiteTea();
        } else if (type == "green") {
            tea = new GreenTea();
        } else if (type == "black") {
            tea = new BlackTea();
        } else if (type == "herbal") {
            tea = new HerbalTea();
        }
        return tea;
    }
}

Lets see how the client code looks now;

public class TeaShop {

    SimpleTeaFactory teaFactory;

    public TeaShop(SimpleTeaFactory teaFactory) {
        this.teaFactory = teaFactory;
    }

    public Tea orderTea(String type) {
        Tea tea;

        // no more concrete instantiation here
        tea = teaFactory.makeTea(type);
        tea.prepare();
        tea.addFlavour();
        tea.decorate();

        return tea;
    }
}


Hay what's the advantage of this? We are just pushing the problem of object creation to another object?

Not really. Now every time a new type of tea is introduced in our tea shop, we do not have to break the code in our TeaShop class and ofcaurse same advantage applies for all the other client classes of SimpleTeafactory class. Now there is only one place to change, that is SimpleTeafactory class.

Lets see the design of this Simple Factory;

 

 

This design is called "Simple Factory". This is not a full pledged design pattern rather a very usfull programmin idiom.

Note:
In the class diagram Product is mentioned as a Interface.  Remember in coding prospective it can well be a Abstract class as well.

 Get the full source code for Simple Factory implementation.

More Challenges

Our tea shop has hired a marketing consultant and he has proposed to increas the verity of tea in a differnt dimention. Add the flavour of country in the served tea. Now its going to be Sri Lankan (Ceylon) tea for Asian flavour lovers and Kenyan tea for African flavour lovers.

 

 

Problem

Can we continue using our "Simple Factory" idiom and add more 'else if' s to our makeTea method in SimpleTeaFactory class? Yes you can. BUT there is so much of cultural differences in making Sri Lankan tea over Kenyan tea. Isn't it? If we are going to continue with 'Simple Factory', we are certainly going to miss adding  this cultural zip into making tea.

Solution

What we are going to do is to keep the makeTea method in TeaFactory class, but this time make it an abstract method. Then create TeaFactory sub classes of each regional styles, and let them implement the makeTea factory method in their style.

OK, Now lets see how our codings look like;

 Tea.java

 public abstract class Tea {

    public abstract void prepare();

    public abstract void addFlavour();

    public abstract void decorate();
}

 

SriLankanBlackTea.java

public class SriLankanBlackTea extends Tea {

    public void prepare() {
        System.out.println("SriLankanBlackTea :prepare ");
    }

    public void addFlavour() {
        System.out.println("SriLankanBlackTea :addFlavour ");
    }

    public void decorate() {
        System.out.println("SriLankanBlackTea :decorate ");
    }
}

 

You can see that Our factory class is now abstract to defer instantiate to subclasses

TeaFactory.java

public abstractclass TeaFactory {

    // Our factory method is now abstract
    protected abstract Tea makeTea(String type);

    public Tea orderTea(String type) {
        Tea tea;

        // calls abstract factory method
        tea = makeTea(type);

        // common operations may come here
        tea.prepare();
        tea.addFlavour();
        tea.decorate();

        return tea;
    }
}

 

SriLankanTeaFactory.java

public class SriLankanTeaFactory extends TeaFactory {

    // factory method is implemented here
    public Tea makeTea(String type) {
        Tea tea = null;
        if (type == "white") {
            tea = new SriLankanWhiteTea();
        } else if (type == "green") {
            tea = new SriLankanGreenTea();
        } else if (type == "black") {
            tea = new SriLankanBlackTea();
        }

        return tea;
    }
}

Lets write a small Junit test client to test our factory method implementation.

TeaFactoryTest.java

public class  TeaFactoryTest extends TestCase {

    public TeaFactoryTest(String name) {
        super(name);
    }


    public void testOrderTea() {
        Tea tea;
        SriLankanTeaFactory sriLankanTeaFactory;
        KenyaTeaFactory kenyaTeaFactory;       
       
        sriLankanTeaFactory = new SriLankanTeaFactory();
        tea = sriLankanTeaFactory.orderTea("white");
        assertEquals("SriLankanWhiteTea", tea.getClass().getName());
       
        kenyaTeaFactory = new KenyaTeaFactory();
        tea = kenyaTeaFactory.orderTea("black");
        assertEquals("KenyaBlackTea", tea.getClass().getName());
    }
}

Out put:
SriLankanWhiteTea :prepare
SriLankanWhiteTea :addFlavour
SriLankanWhiteTea :decorate

KenyaBlackTea :prepare
KenyaBlackTea :addFlavour
KenyaBlackTea :decorate

 Get the full Source Code for Simple Factory implementation.

 

Factory Method Pattern

Defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiate to subclasses.

 

 References:
Head First Design Patterns (Head First)  

Current Rating: Rate This Artical:

 Your Feedback: