Factory Design Pattern

Factory design pattern

In this tutorial, we are going to discuss about Factory Design Pattern. Factory design pattern is one of the Creational design pattern. Factory design pattern is used when we have a super class with multiple sub-classes and based on input, we need to return one of the sub-class. This pattern take out the responsibility of instantiation of a class from client program to the factory class.

The Factory design pattern provides a way to encapsulate object creation. Instead of instantiating objects directly using a constructor, this pattern delegates the instantiation process to a specialized method, often called a factory method. This pattern is particularly useful when there is a need to decouple object creation from its usage, allowing for more flexibility and easier maintenance.

Imagine a software development tool that must be able to work with several different kinds of source code repositories, including Git, Subversion, and Mercurial. Each repository type provides a unique method for activities such as commit, pull, and push. When additional repository types need to be added or when actions related to a particular repository change, implementing repository operations directly within the client code can result in a jumbled and difficult-to-maintain codebase.

It is possible to use the Factory design pattern to abstract the process of creating various repository types. The tool creates these objects using a factory method instead of directly instantiating repository instances. The factory method uses configuration or input to decide what kind of repository object to construct. The image below shows an illustration of this.

Factory Design Pattern Example

For instance, the createRepository method of a RepositoryFactory class may return a Git, Subversion, or Mercurial repository object, depending on the arguments. Despite their internal variations, each of these objects would be a subclass of a shared Repository interface, ensuring that client code could interact with them using a uniform set of methods.

Super class

Super class in factory design pattern can be an interface, abstract class or a normal java class. In our example, we have abstract super class with overridden toString() method for testing purpose.

package com.ashok.designpatterns.model;

/**
 * 
 * @author ashok.mariyala
 *
 */
public abstract class MyComputer {  
   public abstract String getRAM();
   public abstract String getHDD();
   public abstract String getCPU();
   
   @Override
   public String toString(){
      return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU();
   }
}

Sub class

Let’s say we have two sub classes MyPersonalComputer and MyServer with below implementation.

package com.ashok.designpatterns.model;

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyPersonalComputer extends MyComputer {
   private String ram;
   private String hdd;
   private String cpu;
   
   public MyPersonalComputer(String ram, String hdd, String cpu){
      this.ram = ram;
      this.hdd = hdd;
      this.cpu = cpu;
   }
   @Override
   public String getRAM() {
      return this.ram;
   }

   @Override
   public String getHDD() {
      return this.hdd;
   }

   @Override
   public String getCPU() {
      return this.cpu;
   }
}

Notice that both the classes are extending MyComputer super class.

package com.ashok.designpatterns.model;

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyServer extends MyComputer {
   private String ram;
   private String hdd;
   private String cpu;
   
   public MyServer(String ram, String hdd, String cpu){
      this.ram=ram;
      this.hdd=hdd;
      this.cpu=cpu;
   }
   @Override
   public String getRAM() {
      return this.ram;
   }

   @Override
   public String getHDD() {
      return this.hdd;
   }

   @Override
   public String getCPU() {
      return this.cpu;
   }
}

Finally the factory class is

package com.ashok.designpatterns.factory;

import com.ashok.designpatterns.model.MyComputer;
import com.ashok.designpatterns.model.MyPersonalComputer;
import com.ashok.designpatterns.model.MyServer;

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyComputerFactory {
   public static MyComputer getComputer(String type, String ram, String hdd, String cpu){
      if("MyPersonalComputer".equalsIgnoreCase(type)) 
         return new MyPersonalComputer(ram, hdd, cpu);
      else if("MyServer".equalsIgnoreCase(type)) 
         return new MyServer(ram, hdd, cpu);
      return null;
   }
}

Note

  1. We can keep Factory class Singleton or we can keep the method that returns the subclass as static.
  2. Notice that based on the input parameter, different subclass is created and returned. getComputer is the factory method.

Now, simple test client program that uses above factory design pattern implementation is as follows,

package com.ashok.designpatterns.test;

import com.ashok.designpatterns.factory.PCFactory;
import com.ashok.designpatterns.factory.MyComputerFactory;
import com.ashok.designpatterns.model.MyComputer;

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyTestFactory {
   public static void main(String[] args) {
      MyComputer pc = MyComputerFactory.getComputer("PersonalComputer","4 GB","500 GB","2.6 GHz");
      MyComputer server = MyComputerFactory.getComputer("MyServer","16 GB","1 TB","2.9 GHz");
      System.out.println("Factory PC Configuration is : " +pc);
      System.out.println("Factory Server Configuration is : " +server);
   }
}

Output

Factory PC Configuration is : RAM= 4 GB, HDD=500 GB, CPU=2.6 GHz
Factory Server Configuration is : RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz
Applications of Factory Pattern

GUI Libraries

Different platforms or operating systems may render GUI elements differently. By using the Factory Pattern, GUI components like buttons, windows, and menus can be created, ensuring that the right type of object is instantiated on various platforms without disclosing the creation mechanism to the client.

Database Connections

Applications may have to control connections to many kinds of databases. Based on the database system type (such as MySQL, PostgreSQL, or MongoDB) provided, Factory Pattern can construct and deliver a suitable database connection object, hiding the instantiation details and giving the client a consistent interface.

E-Commerce Payments Processing

E-commerce platforms may allow various payment methods (such as PayPal, Stripe, and Credit Cards). Based on the chosen payment method, a Payment Gateway Factory might provide the appropriate payment processing object, ensuring that the client is isolated from the instantiation logic and can operate with a consistent interface for payment processing.

Summary

The Factory design Pattern is a way to achieve loose coupling and greater flexibility in object creation. It’s especially useful in systems where the type of objects to create can change depending on circumstances or where there are many types of objects that share a common base class or interface. However, this method may be too much for small projects and might occasionally complicate your code, particularly if you have many separate objects. It’s really beneficial when your software needs to manage a large number of similar items.

That’s all about the Factory Design Pattern. If you have any queries or feedback, please write us email at contact@waytoeasylearn.com. Enjoy learning, Enjoy Design patterns.!!

Factory Design Pattern
Scroll to top