Abstract Factory Design Pattern

Nivedita KumariNivedita Kumari
5 min read

The Abstract Factory Pattern is a creational design pattern that provides an interface for creating families of related objects without specifying their concrete classes. It ensures that the created objects are compatible with each other.(Compatibility means that the objects created by an Abstract Factory belong to the same family or style, ensuring they work well together without mismatches.)

Key Components

  1. Abstract Products (Interfaces/Abstract Classes)

    • Define common behavior for related product types.
  2. Concrete Products (Subclasses)

    • Implement the abstract product interfaces.
  3. Abstract Factory (Interface/Abstract Class)

    • Declares methods to create families of related objects.
  4. Concrete Factories (Subclasses)

    • Implement the abstract factory to create specific product variants.
  5. Client Code

    • Uses only the abstract factory and product interfaces, remaining independent of specific implementations.

Example

Abstract Product-1

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public interface Doctor {
    void treatPatient();
}

Abstract Product-2

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public interface Nurse {
    void assistDoctor();
}

Abstract Product-3

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public interface Medicine {
    void prescribe();
}

Concrete Product-1

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class GovernmentDoctor implements Doctor {
    @Override
    public void treatPatient() {
        System.out.println("Government Doctor treating a patient for free.");
    }
}
package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class PrivateDoctor implements Doctor {
    @Override
    public void treatPatient() {
        System.out.println("Private Doctor treating a patient with specialized care.");
    }
}

Concrete Product-2

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class GovernmentNurse implements Nurse {
    @Override
    public void assistDoctor() {
        System.out.println("Government Nurse assisting the doctor in a public hospital.");
    }
}
package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class PrivateNurse implements Nurse {
    @Override
    public void assistDoctor() {
        System.out.println("Private Nurse assisting the doctor in a private hospital.");
    }
}

Concrete Product-3

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class GovernmentMedicine implements Medicine {
    @Override
    public void prescribe() {
        System.out.println("Providing free government medicine.");
    }
}
package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class PrivateMedicine implements Medicine {
    @Override
    public void prescribe() {
        System.out.println("Prescribing branded medicine.");
    }
}

Abstract Factory

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public interface HospitalFactory {
    Doctor createDoctor();
    Nurse createNurse();
    Medicine createMedicine();
}

Concrete Factories

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class GovernmentHospitalFactory implements HospitalFactory {
    @Override
    public Doctor createDoctor() {
        return new GovernmentDoctor();
    }

    @Override
    public Nurse createNurse() {
        return new GovernmentNurse();
    }

    @Override
    public Medicine createMedicine() {
        return new GovernmentMedicine();
    }
}
package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class PrivateHospitalFactory implements HospitalFactory {
    @Override
    public Doctor createDoctor() {
        return new PrivateDoctor();
    }

    @Override
    public Nurse createNurse() {
        return new PrivateNurse();
    }

    @Override
    public Medicine createMedicine() {
        return new PrivateMedicine();
    }
}

Factory Producer

package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class HospitalFactoryProducer {
    public static HospitalFactory getFactory(String type) {
        if ("GOVERNMENT".equalsIgnoreCase(type)) {
            return new GovernmentHospitalFactory();
        } else if ("PRIVATE".equalsIgnoreCase(type)) {
            return new PrivateHospitalFactory();
        }
        throw new IllegalArgumentException("Unknown hospital type: " + type);
    }
}
package DesignPatterns.Creational.AbstractFactory.HealthCare;

public class Client {
    public static void main(String[] args) {
        // Government Hospital
        System.out.println("Government Hospital Services:");
        HospitalFactory govFactory = HospitalFactoryProducer.getFactory("GOVERNMENT");
        govFactory.createDoctor().treatPatient();
        govFactory.createNurse().assistDoctor();
        govFactory.createMedicine().prescribe();

        // Private Hospital
        System.out.println("\nPrivate Hospital Services:");
        HospitalFactory privateFactory = HospitalFactoryProducer.getFactory("PRIVATE");
        privateFactory.createDoctor().treatPatient();
        privateFactory.createNurse().assistDoctor();
        privateFactory.createMedicine().prescribe();
    }
}

Note:-

  • Scalability: We can easily add more hospital types (e.g., Military Hospital, Charity Hospital).

  • Abstract Factory Pattern: The client code doesn’t need to know how the objects are created—just uses the factory.

Factory Pattern vs. Abstract Factory Pattern

FeatureFactory PatternAbstract Factory Pattern
DefinitionCreates one type of object (e.g., only Doctors or only Nurses).Creates families of related objects (e.g., Doctor, Nurse, and Medicine for a hospital).
Use CaseWhen you need a single category of objects with multiple implementations.When you need multiple related objects that must be used together.
ScalabilityLess scalable, requires changes if more object types are needed.More scalable, allows adding entire new families of objects easily.
ComplexitySimpler, suitable for smaller applications.More complex but useful in enterprise applications.P

Pros

  1. Encapsulates Object Creation (Decoupling)

  • The client doesn’t need to know which concrete class is being instantiated.

  • It hides implementation details, making the system easier to maintain.


  • Ensures that objects that belong together are created together.

  • Avoids mixing objects from different families (e.g., a Government Doctor with a Private Nurse).

Example:

  • In the Healthcare System, using GovernmentHospitalFactory guarantees that we get:

    • GovernmentDoctor

    • GovernmentNurse

    • GovernmentMedicine


  1. Scalability (Easy to Extend)

  • Adding a new hospital type (e.g., MilitaryHospitalFactory) is easy without modifying existing code.

  • Just create a new factory that implements HospitalFactory.


  1. Encourages Separation of Concerns (Better Code Organization)

  • Each factory class has a single responsibility.

  • The client code doesn’t get cluttered with new object creation logic.

Cons

  1. Increased Complexity (Too Many Classes)

  • The pattern introduces multiple new interfaces and classes, which can bloat the project.

  • For small projects, this may be unnecessary.

  1. Difficult to Add New Products

  • If we need to add a new type of product (e.g., Ambulance), we must update every factory.

  • This violates the Open-Closed Principle (because we modify existing code).

  1. Not Always Necessary (Overkill for Simple Applications)

  • If an application only creates one type of object (e.g., just Doctors), using Factory Pattern is simpler.

  • Abstract Factory is best suited for complex systems with multiple object families.

CODE LINK : Hospital Factory Github Link

0
Subscribe to my newsletter

Read articles from Nivedita Kumari directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nivedita Kumari
Nivedita Kumari

I am wokring as SDE-1 at BetterPlace