GoF Definition: Define an interface for creating an object, but let subclasses decide which class to instantiate. The factory method lets a class defer instantiation to subclasses.
The concept can be best described with the examples below.
Suppose you have two different types of televisions—one with an LED screen and another with an LCD screen. If any of these starts malfunctioning, you will call a TV repairman to request a visit to your residence. The repairman must ask first what kind of TV is nonoperational. As per your input, he’ll carry the required instruments with him.
In a Windows application, we may have different database users (e.g., one user uses Oracle and one may use Sql Server). Now whenever we need to insert data in our database we need to create either an SqlConnection or an OracleConnection first; only then we can proceed. If we put them into simple if-else, we need to repeat lots of codes and it doesn’t look good. We can use the factory pattern to solve these types of problems. The basic structure is defined with an abstract class; our subclasses will be derived from this class. The subclasses will take the responsibility of the instantiation process.
Here I have created all classes into a single file. Please go through the code. Note that here we have two animal types—Duck and Tiger. And whenever we try to use a new type, Lion, which was not implemented earlier, an exception will be thrown. If you want to omit this extra part, you can do that. In that case, we also do not need to take precautions for any exceptions.
High-level structure of the parts of the program is as follows:
package factory.pattern.demo;
interface IAnimal
{
void Speak();
}
class Duck implements IAnimal
{
@Override
public void Speak()
{
System.out.println("Duck says Pack-pack");
}
}
class Tiger implements IAnimal
{
@Override
public void Speak()
{
System.out.println("Tiger says: Halum..Halum");
}
}
abstract class IAnimalFactory
{
public abstract IAnimal
/*if we cannot instantiate in later stage, we’ll throw exception*/
GetAnimalType(String type) throws Exception;
}
class ConcreteFactory extends IAnimalFactory
{
@Override
public IAnimal GetAnimalType(String type) throws Exception
{
switch (type)
{
case "Duck":
return new Duck();
case "Tiger":
return new Tiger();
default:
throw new Exception( "Animal type : "+type+" cannot be instantiated");
}
}
}
class FactoryPatternEx
{
public static void main(String[] args) throws Exception
{
System.out.println("***Factory Pattern Demo*** ");
IAnimalFactory animalFactory = new ConcreteFactory();
IAnimal DuckType=animalFactory.GetAnimalType("Duck");
DuckType.Speak();
IAnimal TigerType = animalFactory.GetAnimalType("Tiger");
TigerType.Speak();
//There is no Lion type. So, an exception will be thrown
IAnimal LionType = animalFactory.GetAnimalType("Lion");
LionType.Speak();
}
}
If you do not want to see the exception, just do not try to create the Lion type here (i.e., comment out the code).