learnings

Abstract Factory

Abstract Factory - is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes.

This pattern is used when:

The pattern operates with four entities:

  1. AbstractFactory - declares an interface for operations that create abstract products
  2. ConcreteFactory - implements the creation interface for a specific concrete family of products
  3. AbstractProduct - declares an interface for a type of product
  4. ConcreteProduct - defines a implementation of the abstract product

Implementations

Python

from abc import ABC, abstractmethod


# Abstract Product: GUI Button
class Button(ABC):
    @abstractmethod
    def paint(self) -> None:
        pass

    @abstractmethod
    def on_click(self) -> None:
        pass


# Abstract Product: Checkbox
class Checkbox(ABC):
    @abstractmethod
    def paint(self) -> None:
        pass

    @abstractmethod
    def set_checked(self, checked: bool) -> None:
        pass


# Concrete Product: Windows Button
class WindowsButton(Button):
    def paint(self) -> None:
        print("Painting Windows button")

    def on_click(self) -> None:
        print("Windows button clicked")


# Concrete Product: Windows Checkbox
class WindowsCheckbox(Checkbox):
    def paint(self) -> None:
        print("Painting Windows checkbox")

    def set_checked(self, checked: bool) -> None:
        print(f"Windows checkbox set to {checked}")


# Concrete Product: MacOS Button
class MacOSButton(Button):
    def paint(self) -> None:
        print("Painting macOS button")

    def on_click(self) -> None:
        print("macOS button clicked")


# Concrete Product: macOS Checkbox
class MacOSCheckbox(Checkbox):
    def paint(self) -> None:
        print("Painting macOS checkbox")

    def set_checked(self, checked: bool) -> None:
        print(f"macOS checkbox set to {checked}")


# Abstract Factory
class GUIFactory(ABC):
    @abstractmethod
    def create_button(self) -> Button:
        pass

    @abstractmethod
    def create_checkbox(self) -> Checkbox:
        pass


# Concrete Factory: Windows
class WindowsFactory(GUIFactory):
    def create_button(self) -> Button:
        return WindowsButton()

    def create_checkbox(self) -> Checkbox:
        return WindowsCheckbox()


# Concrete Factory: macOS
class MacOSFactory(GUIFactory):
    def create_button(self) -> Button:
        return MacOSButton()

    def create_checkbox(self) -> Checkbox:
        return MacOSCheckbox()


# Client code
def client_code(factory: GUIFactory) -> None:
    button = factory.create_button()
    checkbox = factory.create_checkbox()

    button.paint()
    button.on_click()

    checkbox.paint()
    checkbox.set_checked(True)


if __name__ == "__main__":
    windows_factory = WindowsFactory()
    client_code(windows_factory)

    print()

    macos_factory = MacOSFactory()
    client_code(macos_factory)