Skip to main content
Practice Problems

Abstract factory pattern

Abstract Factory is creational design pattern that provides interface for creating families of interrelated objects without specifying concrete classes. This pattern is especially useful when your code must work with different "families" of objects, but remain independent from concrete implementations.

Idea:

"Abstract Factory" helps create products belonging to one family through common interface, hiding implementation details.


When to Apply "Abstract Factory"?

  • When program should have several "families" of products that are used together. For example, different themes (Theme) in UI (light, dark) or different engines (2D/3D).
  • When need to create objects depending on specific configuration or runtime environment (e.g., Web vs. Mobile), but code shouldn't depend on details of this configuration.
  • When need to hide from client logic of choosing concrete implementation, so it can be easily changed without affecting rest of code.

How It Works

1. Defining Product Families

First we define types of products that should be created together. For example: Button, Checkbox, Modal for different platforms or themes.

2. Creating Abstract Interfaces

Each product family has abstract interfaces. For example: Button with render() method and Checkbox with toggle() method.

3. Implementing Concrete Products

For each platform (or theme) concrete classes are created implementing these interfaces. For example: MacButton, MacCheckbox and WinButton, WinCheckbox.4

4. Abstract Factory

Abstract factory defines methods for creating products (e.g., createButton(), createCheckbox()) and returns abstract types. Concrete factories (MacFactory, WinFactory) override these methods, creating corresponding objects.

5. Client Code

Client works only with abstract factory and abstract products, not binding to concrete implementations. Factory choice (Mac vs. Win) can be configured without changing rest of code.


Example (TypeScript)

ts
// 1. Abstract product interfaces interface Button { render(): void; } interface Checkbox { toggle(): void; } // 2. Concrete products class MacButton implements Button { render(): void { console.log("Mac button rendered"); } } class WinButton implements Button { render(): void { console.log("Windows button rendered"); } } class MacCheckbox implements Checkbox { toggle(): void { console.log("Mac checkbox toggled"); } } class WinCheckbox implements Checkbox { toggle(): void { console.log("Windows checkbox toggled"); } } // 3. Abstract factory interface GUIFactory { createButton(): Button; createCheckbox(): Checkbox; } // 4. Concrete factories class MacFactory implements GUIFactory { createButton(): Button { return new MacButton(); } createCheckbox(): Checkbox { return new MacCheckbox(); } } class WinFactory implements GUIFactory { createButton(): Button { return new WinButton(); } createCheckbox(): Checkbox { return new WinCheckbox(); } } // 5. Client code function runApp(factory: GUIFactory) { const button = factory.createButton(); button.render(); const checkbox = factory.createCheckbox(); checkbox.toggle(); } // Can easily substitute factory // Mac UI runApp(new MacFactory()); // Windows UI runApp(new WinFactory());

Source

Abstract Factory is excellent for large systems where there are several variants of same "family" of products. It makes code flexible, allowing to substitute entire sets of objects without changing main logic. However, due to increased number of classes this pattern may be excessive if you only occasionally need to switch between implementations or manage small number of entities.

Read more about Abstract Factory here.

Content

When to Apply "Abstract Factory"?How It WorksExample (TypeScript)Source

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems