Abstract Factory Design Pattern

Abstract Factory Design Pattern

In this tutorial, we are going to discuss about the Abstract Factory Design Pattern. The Abstract Factory Design Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It encapsulates the creation process, allowing you to switch between different sets of related objects seamlessly. Think of it as a super factory – a factory of factories.

Consider a scenario where software needs to function across multiple platforms (E.g., Windows, Linux and Mac OS), each requiring a different set of UI elements that conform to the platform’s standards.

Abstract Factory Design Pattern

Solution: The Abstract Factory pattern provides a way to encapsulate a group of individual factories with a common goal. It allows a client to create objects from a family of classes without specifying exact classes. This pattern is ideal for the software, as it can use different factories to produce UI elements that are appropriate for the platform it’s running on. This results in ensuring platform consistency and reducing platform-specific code.

Real-Life Example

Abstract Factory Pattern

To further grasp it, let’s use an example. If you want to buy a phone, you would go to a store selling phones and ask the seller for the one you want. Since the vendor sells phones from several manufacturers, he would then give you the phone you desire. Thus, as you can see, a phone store is a factory of phones that houses devices made by many factories. The phone store can be considered a super factory.

Abstract Factory Design Pattern is similar to Factory design pattern and it’s factory of factories. If you are familiar with factory design pattern in java, you will notice that we have a single Factory class that returns the different sub-classes based on the input provided and factory class uses if-else or switch statement to achieve this. Like factory design pattern, we will use the same super class and sub-classes.

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 Server 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 Computer 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;
   }
}

Now we need Factory Class for Each subclass. First of all we need to create a Abstract Factory interface or abstract class.

package com.ashok.designpatterns.abstractfactory;

import com.ashok.designpatterns.model.MyComputer;

/**
 * 
 * @author ashok.mariyala
 *
 */
public interface MyComputerAbstractFactory {
  public MyComputer createComputer();
}
package com.ashok.designpatterns.abstractfactory;

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

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyPersonalComputerFactory implements MyComputerAbstractFactory {

   private String ram;
   private String hdd;
   private String cpu;
   
   public MyPersonalComputerFactory(String ram, String hdd, String cpu){
      this.ram=ram;
      this.hdd=hdd;
      this.cpu=cpu;
   }
   @Override
   public MyComputer createComputer() {
      return new MyPersonalComputer(ram,hdd,cpu);
   }
}
package com.ashok.designpatterns.abstractfactory;

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

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyServerFactory implements MyComputerAbstractFactory {

   private String ram;
   private String hdd;
   private String cpu;
   
   public MyServerFactory(String ram, String hdd, String cpu){
      this.ram=ram;
      this.hdd=hdd;
      this.cpu=cpu;
   }
   @Override
   public MyComputer createComputer() {
      return new MyServer(ram,hdd,cpu);
   }
}

Now we will create a consumer class that will provide the entry point for the client classes to create sub-classes.

package com.ashok.designpatterns.abstractfactory;

import com.ashok.designpatterns.model.MyComputer;

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyComputerFactory {
   public static MyComputer getComputer(MyComputerAbstractFactory factory){
      return factory.createComputer();
   }
}

Now, lets write a simple test method and see how to use the abstract factory to get the instance of sub-classes.

package com.ashok.designpatterns.test;

import com.ashok.designpatterns.abstractfactory.MyPersonalComputerFactory;
import com.ashok.designpatterns.abstractfactory.MyServerFactory;
import com.ashok.designpatterns.factory.MyComputerFactory;
import com.ashok.designpatterns.model.MyComputer;

/**
 * 
 * @author ashok.mariyala
 *
 */
public class MyTestDesignPatterns {
   public static void main(String[] args) {
      testAbstractFactory();
   }

   private static void testAbstractFactory() {
      MyComputer pc = com.ashok.designpatterns.abstractfactory.MyComputerFactory.getComputer(new MyPersonalComputerFactory("4 GB","500 GB","2.6 GHz"));
      MyComputer server = com.ashok.designpatterns.abstractfactory.MyComputerFactory.getComputer(new MyServerFactory("16 GB","1 TB","2.9 GHz"));
      System.out.println("AbstractFactory PC Configuration : "+pc);
      System.out.println("AbstractFactory Server Configuration : "+server);
   }
}

Output

AbstractFactory PC Configuration : RAM= 4 GB, HDD=500 GB, CPU=2.6 GHz
AbstractFactory Server Configuration : RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz

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

Abstract Factory Design Pattern
Scroll to top