© Vaskaran Sarcar 2019
Vaskaran SarcarJava Design Patternshttps://doi.org/10.1007/978-1-4842-4078-6_4

4. Factory Method Pattern

Vaskaran Sarcar1 
(1)
Bangalore, Karnataka, India
 

This chapter covers the factory method pattern.

GoF Definition

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory method lets a class defer instantiation to subclasses.

Points To Remember

To understand this pattern, I suggest you go to Chapter 24, which covers the simple factory pattern. The simple factory pattern does not fall directly into the Gang of Four design patterns, so I put the discussion of that pattern in Part II of this book. The factory method pattern will make more sense if you start with the simple factory pattern.

Concept

Here you start your development with an abstract creator class (creator) that defines the basic structure of the application. The subclasses that derive from this abstract class perform the actual instantiation process. The concept will make sense to you when you start thinking about the pattern using the following examples.

Real-World Example

Consider a car manufacturing company that produces different models of a car and runs its business well. Based on the model of the car, different parts are manufactured and assembled.

The company should be prepared for changes where customers can opt for better models in the near future. If the company needs to do a whole new setup for a new model, which demands only a few new features, it can hugely impact its profit margin. So, the company should set up the factory in such a way that it can produce parts for the upcoming models also.

Computer-World Example

Suppose that you are building an application that needs to support two different databases, let’s say Oracle and SQL Server. So, whenever you insert a data into a database, you create a SQL Server–specific connection (SqlServerConnection) or an Oracle server–specific connection (OracleConnection) and then you can proceed. If you put these codes into if-else (or switch) statements, you may need to repeat a lot of code. This kind of code is not easily maintainable because whenever you need to support a new type of connection, you need to reopen your code and place the modifications. A factory method pattern focuses on solving similar problems in application development.

Note Since the simple factory pattern is the simplest form of the factory method pattern, you can consider the same examples here. So, the static getInstance()method of the java.text.NumberFormat class is an example of this category. The createURLStreamHandler(String protocol) of the java.net.URLStreamHandlerFactory interface is another example in this category. You can pass ftp, http, and so forth as different protocols and the method will return a URLStreamHandler for the specific protocol.

Illustration

I am continuing the discussion the simple factory pattern that is covered in Chapter 24. So, I’ll try to improve the implementation. For simplicity, I have placed all classes in this implementation in a single file. So, you do not need to create any separate folders for the individual classes. I suggest that you refer to the associated comments for a better understanding.

Class Diagram

Figure 4-1 shows the class diagram of the factory method pattern.
../images/395506_2_En_4_Chapter/395506_2_En_4_Fig1_HTML.jpg
Figure 4-1

Class diagram

Package Explorer View

Figure 4-2 shows the high-level structure of the program.
../images/395506_2_En_4_Chapter/395506_2_En_4_Fig2_HTML.jpg
Figure 4-2

Package Explorer view

Implementation

Here’s the implementation.
package jdp2e.factorymethod.demo;
interface Animal
{
       void speak();
       void preferredAction();
}
class Dog implements Animal
{
       public void speak()
       {
              System.out.println("Dog says: Bow-Wow.");
       }
       public void preferredAction()
       {
              System.out.println("Dogs prefer barking... ");
       }
}
class Tiger implements Animal
{
       public void speak()
       {
              System.out.println("Tiger says: Halum.");
       }
       public void preferredAction()
       {
              System.out.println("Tigers prefer hunting... ");
       }
}
abstract class AnimalFactory
{
/*Remember that the GoF definition says "....Factory method lets a class defer instantiation to subclasses."
In our case, the following method will create a Tiger or Dog but at this point it does not know whether it will get a Dog or a Tiger. This decision will be taken by the subclasses i.e. DogFactory or TigerFactory. So,in this implementation, the following method is playing the role of a factory (of creation)*/
       public abstract Animal createAnimal();
}
class DogFactory extends AnimalFactory
{
       public Animal createAnimal()
       {
              //Creating a Dog
              return new Dog();
       }
}
class TigerFactory extends AnimalFactory
{
       public Animal createAnimal()
       {
              //Creating a Tiger
              return new Tiger();
       }
}
class FactoryMethodPatternExample {
       public static void main(String[] args) {
              System.out.println("***Factory Pattern Demo*** ");
              // Creating a Tiger Factory
              AnimalFactory tigerFactory =new TigerFactory();
              // Creating a tiger using the Factory Method
              Animal aTiger = tigerFactory.createAnimal();
              aTiger.speak();
              aTiger.preferredAction();
              // Creating a DogFactory
              AnimalFactory dogFactory = new DogFactory();
              // Creating a dog using the Factory Method
              Animal aDog = dogFactory.createAnimal();
              aDog.speak();
              aDog.preferredAction();
       }
}

Output

Here’s the output.
***Factory Pattern Demo***
Tiger says: Halum.
Tigers prefer hunting...
Dog says: Bow-Wow.
Dogs prefer barking...

Modified Implementation

In this implementation, the AnimalFactory class is an abstract class. So, let us take advantage of using an abstract class. Suppose that you want a subclass to follow a rule that can be imposed from its parent (or base) class. So, I am testing such a scenario in the following design.

The following are the key characteristics of the design.
  • Only AnimalFactory is modified as follows (i.e., I am introducing a new makeAnimal() method).

//Modifying the AnimalFactory class.
abstract class AnimalFactory
{
    public Animal makeAnimal()
    {
      System.out.println("I am inside makeAnimal() of AnimalFactory.You cannot ignore my rules.");
        /*
        At this point, it doesn't know whether it will get a Dog or a Tiger. It will be decided by the subclasses i.e.DogFactory or TigerFactory.But it knows that it will Speak and it will have a preferred way of Action.
        */
        Animal animal = createAnimal();
        animal.speak();
        animal.preferredAction();
        return animal;
    }
/*Remember that the GoF definition says "....Factory method lets a class defer instantiation to subclasses."
In our case, the following method will create a Tiger or Dog but at this point it does not know whether it will get a Dog or a Tiger.
This decision will be taken by the subclasses i.e. DogFactory or TigerFactory. So,in this implementation, the following method is playing the role of a factory (of creation)*/
     public abstract Animal createAnimal();
}
  • Client code has adapted these changes:

class ModifiedFactoryMethodPatternExample {
       public static void main(String[] args) {
              System.out.println("***Modified Factory Pattern Demo*** ");
              // Creating a Tiger Factory
              AnimalFactory tigerFactory =new TigerFactory();
              // Creating a tiger using the Factory Method
              Animal aTiger = tigerFactory.makeAnimal();
              //aTiger.speak();
              //aTiger.preferredAction();
              // Creating a DogFactory
              AnimalFactory dogFactory = new DogFactory();
              // Creating a dog using the Factory Method
              Animal aDog = dogFactory.makeAnimal();
              //aDog.speak();
              //aDog.preferredAction();
       }
}

Modified Output

Here’s the modified output.
***Modified Factory Pattern Demo***
I am inside makeAnimal() of AnimalFactory.You cannot ignore my rules.
Tiger says: Halum.
Tigers prefer hunting...
I am inside makeAnimal() of AnimalFactory.You cannot ignore my rules.
Dog says: Bow-Wow.
Dogs prefer barking...

Analysis

In each case, you see the message (or warning) “…You cannot ignore my rules.”

Q&A Session

  1. 1.

    Why have you separated the CreateAnimal() method from client code?

    It is my true intention. I want the subclasses to create specialized objects. If you look carefully, you will find that only this “creational part” is varying across the products. I discuss this in detail in the Q&A session on the simple factory pattern (see Chapter 24).

     
  2. 2.
    What are the advantages of using a factory like this?
    • You are separating code that can vary from the code that does not vary (i.e., the advantages of using a simple factory pattern is still present). This technique helps you easily maintain code.

    • Your code is not tightly coupled; so, you can add new classes like Lion, Beer, and so forth, at any time in the system without modifying the existing architecture. So, you have followed the “closed for modification but open for extension” principle.

     
  3. 3.

    What are the challenges of using a factory like this?

    If you need to deal with a large number of classes, then you may encounter maintenance overhead.

     
  4. 4.

    I see that the factory pattern is supporting two parallel hierarchies. Is this correct?

    Good catch. Yes, from the class diagram (see Figure 4-3), it is evident that this pattern supports parallel class hierarchies.

     
../images/395506_2_En_4_Chapter/395506_2_En_4_Fig3_HTML.jpg
Figure 4-3

The two class hierarchies in our example

So, in this example, AnimalFactory, DogFactory, and TigerFactory are placed in one hierarchy, and Animal, Dog, and Tiger are placed in another hierarchy. So, the creators and their creations/products are two hierarchies running in parallel.
  1. 5.

    I should always mark the factory method with an abstract keyword so that subclasses can complete them. Is this correct?

    No. You may be interested in a default factory method if the creator has no subclasses. And in that case, you cannot mark the factory method with the abstract keyword.

    To show the real power of the factory method pattern, you may need to follow a similar design, which is implemented here.

     
  2. 6.

    It still appears to me that the factory method pattern is not much different from simple factory. Is this correct?

    If you look at the subclasses in the examples in both chapters, you may find some similarities. But you should not forget the key aim of the factory method pattern is that it is supplying the framework through which different subclasses can make different products. But in a simple factory, you cannot vary the products like you can with the factory method pattern. Think of simple factory as a one-time deal but most importantly, your creational part will not be closed for modification. Whenever you want to add a new stuff, you need to add an if/else block or a switch statement in the factory class of your simple factory pattern.

    In this context, remember the GoF definition: the factory method lets a class defer instantiation to subclasses. So, in our simple factory pattern demonstration, you used a concrete class only (SimpleFactory). You did not need to override the createAnimal() method and there was no subclass that participated in the final decision/product making process. But if you try to code to an abstract class (or interface), that is always considered a good practice, and this mechanism provides you the flexibility to put some common behaviors in the abstract class.

     

Note

In the simple factory pattern, you simply segregate the instantiation logic from client code. In this case, it knows about all the classes whose objects it can create. On the other hand, when using a factory method pattern, you delegate the object creation to subclasses. Also, the factory method is not absolutely sure about the product subclasses in advance.

  1. 7.

    In the factory method pattern, I can simply use a subclassing mechanism (i.e., using inheritance) and then implement the factory method (that is defined in the parent class). Is this correct?

    The answer to this question is yes if you want to strictly follow the GoF definitions. But it is important to note that in many applications/implementations, there is no use of an abstract class or interface; for example, in Java, an XML reader object is used like this:

     
//Some code before…
XMLReader xmlReader1 = XMLReaderFactory.createXMLReader();
//Some code after

XMLReaderFactory is a final class in Java. So, you cannot inherit from it.

But when you use SAXPaserFactory, as follows, you are using an abstract class SAXParserFactory.
//some code before….
SAXParserFactory factory = SAXParserFactory.newInstance();
              SAXParser parser = factory.newSAXParser();
              XMLReader xmlReader2 = parser.getXMLReader();
//Some code after
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.158.32