Open In App

Abstract Factory Pattern | JavaScript Design Patterns

Last Updated : 30 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Abstract Factory Pattern is to abstract the process of object creation by defining a family of related factory methods, each responsible for creating a different type of object. These factory methods are organized within an abstract factory interface or class, and the client code uses this interface to create objects.

Example of Abstract Method in JavaScript Design Patterns:

Imagine, we’re building a UI component library that supports multiple themes (e.g., light and dark themes). We want to create sets of UI components like buttons, input fields, and tooltips for each theme.

Below is the implementation of the above example:

Javascript




// Abstract factory for creating UI components
class UIFactory {
  createButton() {}
  createInputField() {}
  createTooltip() {}
}
 
// Concrete factory for light theme components
class LightThemeFactory extends UIFactory {
  createButton() {
    return new LightThemeButton();
  }
  createInputField() {
    return new LightThemeInputField();
  }
  createTooltip() {
    return new LightThemeTooltip();
  }
}
 
// Concrete factory for dark theme components
class DarkThemeFactory extends UIFactory {
  createButton() {
    return new DarkThemeButton();
  }
  createInputField() {
    return new DarkThemeInputField();
  }
  createTooltip() {
    return new DarkThemeTooltip();
  }
}
 
// Abstract product for buttons
class Button {}
 
// Concrete product for light theme buttons
class LightThemeButton extends Button {
  constructor() {
    super();
    console.log('Light theme button created');
  }
}
 
// Concrete product for dark theme buttons
class DarkThemeButton extends Button {
  constructor() {
    super();
    console.log('Dark theme button created');
  }
}
 
// Usage
const lightFactory = new LightThemeFactory();
const lightButton = lightFactory.createButton(); // Output: Light theme button created
 
const darkFactory = new DarkThemeFactory();
const darkButton = darkFactory.createButton(); // Output: Dark theme button created


Output

Light theme button created
Dark theme button created





Key components of Abstract factory Pattern

  • Abstract Factory: This is an interface or an abstract class that declares a set of factory methods for creating a family of related objects.
  • Concrete Factory: These are the implementations of the abstract factory interface. Each concrete factory is responsible for creating a specific family of related objects.
  • Abstract Products: These are interfaces or abstract classes that declare the common set of methods for the objects within a family.
  • Concrete Products: These are the actual implementations of the abstract products. Each concrete product is specific to a particular family and is created by a corresponding concrete factory.
  • Client: The client code interacts with the abstract factory and abstract product interfaces.

Step wise Code understanding by taking Key Component

Abstarct Factory: Implement an abstract factory, UIFactory, that defines the blueprint for creating UI components.

Javascript




// Abstract factory for creating UI components
class UIFactory {
  createButton() {}
  createInputField() {}
  createTooltip() {}
}


Concrete Factory: Create concrete factories for different themes: LightThemeFactory and DarkThemeFactory, each inheriting from the UIFactory.

Javascript




// Concrete factory for light theme components
class LightThemeFactory extends UIFactory {
  createButton() {
    return new LightThemeButton();
  }
  createInputField() {
    return new LightThemeInputField();
  }
  createTooltip() {
    return new LightThemeTooltip();
  }
}


Javascript




//Concrete factory for dark theme components
class DarkThemeFactory extends UIFactory {
  createButton() {
    return new DarkThemeButton();
  }
  createInputField() {
    return new DarkThemeInputField();
  }
  createTooltip() {
    return new DarkThemeTooltip();
  }
}


Abstract Product: Define abstract product classes for various UI components, such as Button.

Javascript




// Abstract product for buttons
class Button {}


Concrete Product: Create concrete product classes, such as LightThemeButton and DarkThemeButton, that inherit from the abstract product classes.

Javascript




// Concrete product for light theme buttons
class LightThemeButton extends Button {
  constructor() {
    super();
    console.log('Light theme button created');
  }
}


Javascript




// Concrete product for dark theme buttons
class DarkThemeButton extends Button {
  constructor() {
    super();
    console.log('Dark theme button created');
  }
}


When a UI component is created, it should log a message indicating which theme it belongs to. For example, a button created by the light theme factory should display “Light theme button created.”

Abstract Factory Pattern allows us to create entire families of related objects that are compatible with each other. The client code remains unaware of the specific implementations.

Advantages of the Abstract Factory Pattern

  • Consistency: Abstract factories patterns ensure that the objects created within a family are compatible with each other. This helps us to maintain the consistency in our application, as we can ensure that all the objects created by the factory work together.
  • Flexibility: Abstract Factory pattern allows us to switch between different families of objects by using different concrete factories. This is especially useful when we need to support multiple variations of a product or when we want to change the behavior of our application by swapping out factories at runtime.
  • Extensibility: Basically, we can add new concrete factories to support new product families without modifying existing client code. This makes the system more extensible, allowing for the easy addition of new features or components.
  • Testability: Abstract factories patterns make it very easier to write unit tests and mock objects. By creating a factory interface, we can simply create mock or test-specific implementations to facilitate testing without affecting the rest of our code.
  • Encapsulation of Object Creation: Abstract Factory pattern encapsulates the creation of objects. This means that the client code does not need to be aware of the specific classes it is instantiating, promoting loose coupling between the client and the concrete objects.

Disadvantages of the Abstract Factory Pattern

  • Tight Coupling: Suppose if we needs to add new products or make changes to existing ones, than we need to modify both the abstract factory interface and the concrete factory implementations. This can lead to tight coupling between the factories and their products, potentially violating the Open-Closed Principle.
  • Increased Complexity: We need to define interfaces for factories and their product families, create concrete factory implementations, and manage the relationships between factories and products.
  • Code Duplication: While implementing concrete factories patterns for different product families, we end up with duplicate code for creating similar types of objects across multiple factories.
  • Reduced Runtime Flexibility: Once we choose a concrete factory to create objects, it is typically challenging to switch to a different factory at runtime. This limitation can restrict your ability to adapt to changing requirements dynamically.
  • Limited Use Cases: Abstract Factory pattern is most valuable in scenarios where there are multiple related product families with interchangeable components. In simpler applications, the overhead of implementing and maintaining factories may not be justified.

Conclusion

Abstract Factory Pattern promotes the creation of families of related objects while keeping the code decoupled, maintainable, and adaptable to changing requirements or platforms. It’s a powerful tool for managing object creation in complex systems.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads