Factory pattern is one of the Creational design patterns which is most frequently used by software developers.
This pattern takes the responsibility of creating objects for sub classes, based on the input parameter(s) given to Factory Method in Factory Class.
Clients need to know, how to communicate with the factory method by passing appropriate parameter(s) to get one of the subclass (subcategory) object.
Parent class (super class) could be abstract class or interface. Let us learn this pattern through an example.
Example:
Consider a Car dealer (client), who likes to get the brochures of newly launched Cars from a manufacturer. The client knows only the names of the cars, which the client could pass as parameter to the Car Factory. Now it is the responsibility of the Car factory to create one of the suitable brochures and send it back to the client.
Example Diagram:
Design Diagram:
Now let us jump into coding…
Creating Top Level Class (Super Class):
A top level class may be an interface or an abstract class. In our example, we have defined our super class as an abstract class. CarBrouchure abstract class is an abstraction for various car brochures. This class declares three abstract methods, which would be then overridden by respective subclasses.
CarBrouchure.java
package com.learningupskills.designpattern.factorymethod;
public abstract class CarBrochure {
public abstract String getCarModelName();
public abstract void printCarSpecifications();
public abstract int getDiscountPercentage();
/** Get Random Number between min and max value **/
protected int getRandomValue (int min, int max)
{
return (int)(Math.random()*(max-min+1)+min);
}
public void printCarDetails()
{
System.out.println("Car Name :"+getCarModelName());
System.out.println("Car Specifications: ");
printCarSpecifications();
System.out.println("Discount percentage :"+getDiscountPercentage());
}
}
Creating Concrete Subclasses (Child Class):
We have 4 different car brochure subclasses including a subclass for invalid input parameter. All these brochure subclasses ‘extends CarBrouchure’ class and override all the abstract methods.
PullingMule.java
package com.learningupskills.designpattern.factorymethod;
class PullingMule extends CarBrochure {
@Override
public String getCarModelName() {
return CarType.PULLINGMULE.toString();
}
@Override
public void printCarSpecifications() {
System.out.println("FuelType : Diesel");
System.out.println("No of Cylinders : 4");
System.out.println("Max Torque : 150Nm@4400rpm");
System.out.println("TransmissionType : Manual");
System.out.println("Maintenence Cost : 5000");
}
@Override
public int getDiscountPercentage() {
return getRandomValue(10,20);
}
}
RunningCheetah.java
package com.learningupskills.designpattern.factorymethod;
class RunningCheetah extends CarBrochure {
@Override
public String getCarModelName() {
return CarType.RUNNINGCHEETAH.toString();
}
@Override
public void printCarSpecifications() {
System.out.println("FuelType : Petrol");
System.out.println("No of Cylinders : 4");
System.out.println("Max Torque : 120Nm@3500rpm");
System.out.println("TransmissionType : Automatic");
System.out.println("Maintenence Cost : 3000");
}
@Override
public int getDiscountPercentage() {
return getRandomValue(15,25);
}
}
PowerHorse.java
package com.learningupskills.designpattern.factorymethod;
class PowerHorse extends CarBrochure {
@Override
public String getCarModelName() {
return CarType.POWERHORSE.toString();
}
@Override
public void printCarSpecifications() {
System.out.println("FuelType : Petrol");
System.out.println("No of Cylinders : 4");
System.out.println("Max Torque : 100Nm@5500rpm");
System.out.println("TransmissionType : Automatic");
System.out.println("Maintenence Cost : 3500");
}
@Override
public int getDiscountPercentage() {
return getRandomValue(1,5);
}
}
NoCarBrochure.java
package com.learningupskills.designpattern.factorymethod;
class NoCarBrochure extends CarBrochure{
@Override
public String getCarModelName() {
return "Invalid Car ";
}
@Override
public void printCarSpecifications() {
System.out.println("NA");
}
@Override
public int getDiscountPercentage() {
return 0;
}
}
Creating Brochure Type enum:
The CarType enum is responsible for different brochure types.
CarType.java
package com.learningupskills.designpattern.factorymethod;
public enum CarType {
POWERHORSE,
PULLINGMULE,
RUNNINGCHEETAH
}
Creating Factory Class:
The core class in Factory Design Pattern is the factory class and is responsible for creating relevant subclass based on the input parameter(s). In our example, CarSalesFactory class is responsible for creating car brochures based on the name of car.
CarSalesFactory.java
package com.learningupskills.designpattern.factorymethod;
public class CarSalesFactory {
public static CarBrochure getCarbrochure(CarType type) {
if (type == null) {
return new NoCarBrochure();
}
if (type == CarType.POWERHORSE) {
return new PowerHorse();
} else if (type == CarType.PULLINGMULE) {
return new PullingMule();
} else if (type == CarType.RUNNINGCHEETAH) {
return new RunningCheetah();
} else {
return new NoCarBrochure();
}
}
}
Creating Client Class:
The Client class ‘CarDelear’, which calls the factory class ‘CarSalesFactory’, to get brochure by giving car name as parameter.
CarDealer.java
package com.learningupskills.designpattern.factorymethod.client;
import com.learningupskills.designpattern.factorymethod.CarSalesFactory;
import com.learningupskills.designpattern.factorymethod.CarType;
import com.learningupskills.designpattern.factorymethod.CarBrochure;
public class CarDealer {
public static void main(String[] args) {
CarBrochure runningCheetah = CarSalesFactory.getCarbrochure(CarType.RUNNINGCHEETAH);
CarBrochure powerHouse = CarSalesFactory.getCarbrochure(CarType.POWERHORSE);
CarBrochure pullingMule = CarSalesFactory.getCarbrochure(CarType.PULLINGMULE);
CarBrochure noCar = CarSalesFactory.getCarbrochure(null);
System.out.println("**********************************************************");
runningCheetah.printCarDetails();
System.out.println("**********************************************************");
powerHouse.printCarDetails();
System.out.println("**********************************************************");
pullingMule.printCarDetails();
System.out.println("**********************************************************");
noCar.printCarDetails();
}
}
Running CarDealer:
If CarDealer needs brochure for PullingMule , dealer can contact CarSalesFactory with car type parameter as given below:
CarBrochure pullingMule = CarSalesFactory.getCarbrochure(CarType.PULLINGMULE);
Result
Car Name :RUNNINGCHEETAH
Car Specifications:
FuelType : Petrol
No of Cylinders : 4
Max Torque : 120Nm@3500rpm
TransmissionType : Automatic
Maintenence Cost : 3000
Discount percentage :23
Car Name :POWERHORSE
Car Specifications:
FuelType : Petrol
No of Cylinders : 4
Max Torque : 100Nm@5500rpm
TransmissionType : Automatic
Maintenence Cost : 3500
Discount percentage :3
Car Name :PULLINGMULE
Car Specifications:
FuelType : Diesel
No of Cylinders : 4
Max Torque : 150Nm@4400rpm
TransmissionType : Manual
Maintenence Cost : 5000
Discount percentage :12
Car Name :Invalid Car
Car Specifications:
NA
Discount percentage :0