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

24. Simple Factory Pattern

Vaskaran Sarcar1 
(1)
Bangalore, Karnataka, India
 

This chapter covers the simple factory pattern.

Intent

Create an object without exposing the instantiation logic to the client.

Concept

In object-oriented programming, a factory is a special kind of object that can create other objects. A factory can be invoked in many ways, but most often, it uses a method that can return objects with varying prototypes. Any subroutine that can help create these new objects is considered a factory. The ultimate purpose of using a factory method is to abstract the object creational mechanism (or process) from the consumers of the application.

Real-World Example

Consider a car manufacturing company that manufactures different models of a car. They must have a factory with different production units. Some of these units can produce the parts that are common to all models, while other units are dedicated to produce the model-specific parts. When they make the final product, they assemble the model-specific parts with the common parts. From a client’s point of view, a car is built from a car factory; the client does not know how the car is built. But if you investigate further, you see that based on the model of the car, a production unit of the factory varies the parts. For example, a particular car model can support a manual gearbox only and another model can support both the automatic and manual gearbox. So, based on the model of the car, the car factory constructs the particular gearbox for the car.

Consider a simpler example. When a kid demands a toy from his/her parent, the child does not know how the parent will fulfill the demand. The parent, in this case, is considered a factory for their small child. Now think from the parent’s point of view. The parent can make the toy himself/herself or purchase a toy from a shop to make their kid happy.

Computer-World example

The simple factory pattern is very common to software applications, but before we proceed further, you must remember these points.
  • A simple factory is not treated as a standard design pattern in the GoF’s famous book, but the approach is common to any application that you write where you want to separate the code that varies a lot from the part of code that does not vary. It is assumed that you try to follow this approach in any application you write.

  • A simple factory is considered the simplest form of factory method patterns (or abstract factory patterns). So, you can assume that any application that follows either the factory method pattern or the abstract factory pattern, also supports the concept of simple factory pattern’s design goals.

Note

The static getInstance()method of the java.text.NumberFormat class is an example of this category.

Let’s follow the implementation in which I discuss this pattern in a common use case.

Illustration

The following are the important characteristics of the following implementation.
  • In this example, there are two types of animals: dogs and tigers. The object creational process depends on users’ input.

  • I assume that each of them can speak and they prefer to perform some actions.

  • SimpleFactory is the factory class and simpleFactory (note that the “s” is not in caps) is an object of the class. In the client code (SimpleFactoryPatternExample class), you see the following line.

preferredType = simpleFactory.createAnimal();
This means that to get a preferredType object, you need to invoke the createAnimal() method of the simpleFactory object. So, using this approach, you are not directly using a “new” operator in the client code to get an object.
  • I have separated the code that varies from the code that are least likely to vary. This approach helps you remove tight coupling in the system. (How? Follow the “Q&A Session” section.)

Note

In some applications, you may notice a slight variation of this pattern where use of parameterized constructors is suggested. So, in those applications, to get a preferredType object, you may need to use a line of code similar to this line: preferredType=simpleFactory.createAnimal(“Tiger”).

Class Diagram

Figure 24-1 shows a class diagram for the simple factory pattern.
../images/395506_2_En_24_Chapter/395506_2_En_24_Fig1_HTML.jpg
Figure 24-1

Class diagram

Package Explorer View

Figure 24-2 shows the high-level structure of the program.
../images/395506_2_En_24_Chapter/395506_2_En_24_Fig2_HTML.jpg
Figure 24-2

Package Explorer view

Implementation

Here’s the implementation.
package jdp2e.simplefactory.demo;
import java.util.Scanner;//Available Java5 onwards
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...");
    }
}
class SimpleFactory
{
    public Animal createAnimal()
    {
        Animal intendedAnimal=null;
        System.out.println("Enter your choice( 0 for Dog, 1 for Tiger)");
        /* To suppress the warning message:Resource leak:'input' is never closed. So,the following line is optional in this case*/
        @SuppressWarnings("resource")
        Scanner input=new Scanner(System.in);
        int choice=Integer.parseInt(input.nextLine());
        System.out.println("You have entered :"+ choice);
        switch (choice)
        {
        case 0:
            intendedAnimal = new Dog();
            break;
        case 1:
            intendedAnimal = new Tiger();
            break;
        default:
            System.out.println("You must enter either 0 or 1");
            //We'll throw a runtime exception for any other choices.
            throw new IllegalArgumentException(" Your choice tries to create an unknown Animal");
        }
        return intendedAnimal;
    }
}
//A client is interested to get an animal who can speak and perform an
//action.
class SimpleFactoryPatternExample
{
    public static void main(String[] args)     {
        System.out.println("*** Simple Factory Pattern Demo*** ");
        Animal preferredType=null;
        SimpleFactory simpleFactory = new SimpleFactory();
        // The code that will vary based on users preference.
        preferredType = simpleFactory.createAnimal();
        //The codes that do not change frequently.
        //These animals can speak and prefer to do some specific actions.
        preferredType.speak();
        preferredType.preferredAction();
    }
}

Output

Here’s the output.

Case1. User input:0

*** Simple Factory Pattern Demo***
Enter your choice( 0 for Dog, 1 for Tiger)
0
You have entered :0
Dog says: Bow-Wow.
Dogs prefer barking...

Case2. User input:1

*** Simple Factory Pattern Demo***
Enter your choice( 0 for Dog, 1 for Tiger)
1
You have entered :1
Tiger says: Halum.
Tigers prefer hunting...

Case3. An unwanted user input:2

*** Simple Factory Pattern Demo***
Enter your choice( 0 for Dog, 1 for Tiger)
2
You have entered :2
You must enter either 0 or 1Exception in thread "main"
java.lang.IllegalArgumentException:  Your choice tries to create an unknown Animal
    at jdp2e.simplefactory.demo.SimpleFactory.createAnimal(SimpleFactoryPatternExample.java:54)
    at jdp2e.simplefactory.demo.SimpleFactoryPatternExample.main(SimpleFactoryPatternExample.java:68)

Q&A Session

  1. 1.

    In this example, the clients are delegating the objects’ creation through the SimpleFactory. But instead, they could directly create the objects with the “new” operator. Is this correct?

    No. These are the key reasons behind the preceding design.
    • An important object-oriented design principle is to separate the part of your code that is most likely to change from the rest.

    • In this case, only “the objects creational part” varies. I assume that these animals must speak and perform actions, and I do not need to vary that portion of code inside the client. So, in the future, if you need to modify the creational process, you need to change only the createAnimal() method of SimpleFactory class. This client code is unaffected due to those modifications.

    • “How are you creating objects?” is hidden in the client code. This kind of abstraction promotes security.

    • This approach can help you avoid lots of if/else blocks (or switch statements) inside the client code because they make your code look clumsy.

     
  2. 2.
    What are the challenges associated with this pattern?
    • Deciding which object to instantiate becomes complex over time. In those cases, you should prefer the factory method pattern.

    • If you want to add a new animal or delete an existing one, you need to modify the createAnimal() method of the factory class. This approach clearly violates the open-closed principle (which basically says that your code should be open for extension but closed for modification) of SOLID principles.

     

Note

SOLID principles were promoted by Robert C. Martin. You can learn about them at https://en.wikipedia.org/wiki/SOLID .

  1. 3.
    I learned that programming with an abstract class or interface is always a better practice. So, to make a better implementation, you could write something like this:
    abstract class ISimpleFactory
    {
        public abstract IAnimal createAnimal() throws IOException;
    }
    class SimpleFactory extends ISimpleFactory
    {
        //rest of the code
    }

    Is this correct?

    Yes. Programming with the abstract class or an interface is always a better practice. This approach can prevent you from future changes because any newly added classes can simply implement the interface and settle down in the architecture through polymorphism. But if you solely depend on concrete classes, you need to change your code when you want to integrate a new class in the architecture, and in such a case, you violate the rule that says that your code should be closed for modifications.

    So, your understanding is correct. You could use such a construct to make it a better program. But ultimately, you learn the factory method pattern (see Chapter 4), where you need to defer the instantiation process to subclasses. So, you are advised to write programs with an abstract class or an interface in such a case.

     
  2. 4.

    Can you make the factory class (SimpleFactory) static?

    No. In Java, you are not allowed to tag the word static with a top-level class. In other words, by design, the compiler always complains about the top-level static classes in Java.

     
..................Content has been hidden....................

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