Abstract Factory Design Pattern

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
Abstract Products (Interfaces/Abstract Classes)
- Define common behavior for related product types.
Concrete Products (Subclasses)
- Implement the abstract product interfaces.
Abstract Factory (Interface/Abstract Class)
- Declares methods to create families of related objects.
Concrete Factories (Subclasses)
- Implement the abstract factory to create specific product variants.
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
Feature | Factory Pattern | Abstract Factory Pattern |
Definition | Creates 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 Case | When you need a single category of objects with multiple implementations. | When you need multiple related objects that must be used together. |
Scalability | Less scalable, requires changes if more object types are needed. | More scalable, allows adding entire new families of objects easily. |
Complexity | Simpler, suitable for smaller applications. | More complex but useful in enterprise applications.P |
Pros
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 Consistency (Related Objects Stay Together)
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
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
.
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
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.
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).
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
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