Abstract Factory Design Pattern

What is Abstract Factory Design Pattern?

  • It falls under the Creational Design Pattern.
  • It provides an interface for creating families of related or dependent objects without specifying their concrete classes.
  • Abstract Factory patterns is a super factory which will return the best Factory based on the input. 
  • It acts as a factory of factories.
  • It abstracts the client from knowing which factory would be returned.

Table of Contents

Real Life Examples For Abstract Factory Design Pattern

Example 1:

dog photoAnimals are classified into two group types. They are Domestic and Wild. Cat and Dog belong  under domestic category and Lion and Tiger belong under the wild category.

The category “Animal” is an interface. All of those have four legs so it will try to return the animals with four legs. The “Domestic Animal” factory would manage these classes.

For example, if a customer goes to a “Domestic Animal” factory and he requests animals with four legs and weight of 25kg. The factory would return the dog object as it will be more appropriate than the cat.

Tiger PhotoSimilarly, the “Wild Animal” factory will return the appropriate object based on the requirements. If the requirements are 4 legs and 50 kg, the appropriate object would be a “lion” or a “tiger”, it depends. The “Animal” factory will manage these two factories. The “Animal” factory would be abstract to the outside world.

The outside world is uncertain if it is a wild animal or domestic animal factory. If the requirements for this “Animal Factory” is that “I need a wild animal. The legs of that animal should be four, and the weight should be less than 4kg.”

These are the three requirements based on which the “Animal Factory” would try to return the appropriate factory. Here, the appropriate factory would be “Wild animal” factory. And it will try to return the appropriate object for the criteria which would be a “lion”.

Example 2:

Medicine PhotoHere’s another example. If there’s a medical representative and I am the customer. I ask that medical representative about the medicines for fever and cold problems. Based on the requirements, it will try to choose the “Light Fever” factory or “Heavy Fever” factory. The “Light Fever” factory will return the appropriate medicine, in this case. 

Example 3:

file photoLet’s suppose; if you are trying to read some XML files using Dom parser, you will use Abstract Factory because Document Builder Factory is an Abstract Factory. Using this factory, you can get the actual factory object that is getinstance” method. Using that actual factory you can get the concrete objects. Here using Document Builder, I am getting the concrete objects for docFact” object. So, using concrete objects, we can do any number of operations.

When to use Abstract Factory Design Pattern?

  • The client should be independent of how objects are created and for which class object is created.
  • This is helpful when an object needs to be created from a family of classes.

UML Diagram for Abstract Factory Design Pattern

Abstract Factory Design Pattern Java Implementation

Step 1: Create an Interface called "Course"

  • There’s the main class and an interface called “Course”.This course has an abstract method “public String getCurseName.””ProgramminCourse” and “NonprogrammingCourse” are the two classes which implement that interface. The first class will return “Java” because it’s related to programming and the second class will return “DSP” because it’s related to non-programming.
  • These two classes will be handled by the “Course” Factory based on the “courseType”, it will return the better object.
  • If we send programming, it will return “ProgrammingCourse” object, on the other hand, if we send non-programming, it will return the “NonprogrammingCourse” object.
  • “SourceCourseFactory” consists of two abstract methods,”getSource” and “getCourse”.
  • The “CourseFactory” only involves the “getCourse” details. So, the implementation for “getSource” will return null. If you send any sourceType object, it will return null only.

public interface Course
{
    public String getCourseName();
}

Step 2: Create concrete classes that implement the "Course" Interface

public class ProgrammingCourse implements Course
{
    @Override
    public String getCourseName()
    {
       return "Java";
    }
}
public class NonProgrammingCourse implements Course
{
    @Override
    public String getCourseName()
    {
        return "DSP";
    }
}

Step 3: Create an Interface called "Source"

  • The “Source” interface consists of a solo abstract method called “public String getSource”.
  • The implementer classes for “Source” are “offline” and “online”.
  • It will return “Books” for “offline” and “Youtube” for “online”.
  • The “SourceFactory will handle these classes”.It will return the best object based on the input. If the input is online, it will return the “online” object. If it is offline, it will return the “offline” object.
  • If the third kind of input is sent, it will return null only.
  • This factory also extends “SourceCourse” factory, that’s the reason why we have implemented two methods.
  • The “getSource” will return the actual source objects based on the input while “getCourse” will return only null because the “source factory” doesn’t consist of anything related to “Course”.
public interface Source
{
    public String getSourceName();
}

Step 4: Create concrete classes that implement the "Source" Interface

public class Offline implements Source
{
    @Override
    public String getSourceName()
    {
        return "Books";
    }
}
public class Online implements Source
{
    @Override
    public String getSourceName()
    {
        return "YouTube";
    }
}

Step 5: Create an abstract class "SourceCourseFactory"

public abstract class SourceCourseFactory
{
    public abstract Source getSource(String sourceType);
    
    public abstract Course getCourse(String courseType);
}

Step 6: Create a Factory class "CourseFactory" that extends "SourceCourseFactory"

public class CourseFactory extends SourceCourseFactory
{
    @Override
    public Source getSource(String sourceType)
    {
        return null;
    }

    @Override
    public Course getCourse(String courseType)
    {
        if(courseType.equalsIgnoreCase("programming"))
        {
            return new ProgrammingCourse();
        }
        else if(courseType.equalsIgnoreCase("non programming"))
        {
            return new NonProgrammingCourse();
        }
        else
        {
            return null;
        }   
    }

Step 7: Create a Factory class "SourceFactory" that extends "SourceCourseFactory"

<br />public class SourceFactory extends SourceCourseFactory<br />{</p><p>@Override<br />public Source getSource(String sourceType)<br />{<br />if(sourceType.equalsIgnoreCase("online"))<br />{<br />return new Online();<br />}<br />else if(sourceType.equalsIgnoreCase("offline"))<br />{<br />return new Offline();<br />}<br />else<br />{<br />return null;<br />}<br />}</p><p>@Override<br />public Course getCourse(String courseType)<br />{<br />return null;<br />}</p><p>}<br />

Step 8: Create a main class that calls Abstract Factory class to get the real Factory class object and then it uses that object for performing other other operations.

  • This “FactoryCreator” is the “abstract factory” for this application. 
  • This “FactoryCreator” will return the best factory object based on the input. There are two factories “Course” factory and “Source” factory. 
  • If we send “Course”, it will analyze this input and return “CourseFactory” object. 
  • If we send “Source”, it will analyze the data and return “Sourcefactory” object. 
  • If we give any other input means it will return the null. 
  • This main program will use the abstract factory for getting the factory objects.
  • Since we are sending “course” as input this “FactoryCreator” it will return “CourseFactory” object.
  •  So using this “CourseFactory” object, we can call two methods “course.getCourse” and then “course.getSource”.
  • Since the implementation for “getSource” is returned null. 
  • Even if we call “course.getSource” of some input, it will return null. 
  • In this case, we are calling, “course.getCourse” programming. 
  • Here the course will be “programming” it would return “ProgrammingCourse”.Using that object, we are calling “getCourseName”.So  programming “course.getName” is returned Java.
  • The second statement “FactoryCreator.getSourceCourseFactory”. source.
  • So the input for this type will be “source”. It will return “sourceFactory” object. 
  • Using that “sourceFactory” object, we can call two methods. One is “getSource” one is “getSource”.
  • Since the input for this sourceType is “online” so it will return online object. Using that “online” object, we are calling “getSourceName”. So “online” object is Youtube. If we send “Source.getCourse” as input, it will return null because here the implementation for “getCourse” is returning null.
public class ExampleMain
{
    public static void main(String[] args)
    {
        SourceCourseFactory course = FactoryCreator.getSourceCourseFactory("course");

        System.out.println(course.getCourse("programming").getCourseName());

        SourceCourseFactory source = FactoryCreator.getSourceCourseFactory("source");
        System.out.println(source.getSource("online").getSourceName());

    }
}