Abstract Factory Pattern
Is a sub-set of the Factory Method Pattern. Difference:
Each factory (creator) is able to create multiple products, not only one -> ability to create families of related or dependent objects (the abstract factory is a blueprint, that defines what type of Product a factory must be able to instantiate)
Definition
The Abstract Factory Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.
Principle 1
Depend upon abstraction. Do not depend upon concrete classes.
This is known as the Dependency Inversion Principle. It appears similar to the principle, to program against an interface, not an implementation, but goes one step further: It defines, that even the high level classes (e.g. a Zoo class), should depend on an abstraction (e.g. an Animal class), as well a low level classes (e.g. Rabbit), which implements the abstraction.
Some guidelines which help to follow the Dependency Inversion Principle:
No variable should hold reference to a concrete class
No class should derive from a concrete class
No method should overwrite an implemented method of any of its base classes
Naturally, these rules must often be broken, but it is a guideline to strive for.
The interface factory implements multiple creation methods, in which each is supposed to instantiate a different type of object.
Example
Use the Abstract Factory when your code needs to work with various families of related products, but you don’t want it to depend on the concrete classes of those products—they might be unknown beforehand or you simply want to allow for future extensibility.
Find a template example for Python at https://refactoring.guru/design-patterns/abstract-factory/python/example
Applications are * User interfaces (compatability for multiple OS) * Light Theme / Dark Theme implementations
from abc import ABC
class Chair(ABC):
def has_legs(self):
pass
def sit_on(self):
pass
class VictorianChair(Chair):
def has_legs(self):
return True
def sit_on(self):
return False
class ModernChair(Chair):
def has_legs(self):
return False
def sit_one(self):
return True
# Equal interfaces and concretes for other furniture types like Sofa or
# CoffeeTable
# ...
class FurnitureFactory(ABC):
def create_chair(self):
pass
def create_coffee_table(self):
pass
def create_sofa(self):
pass
class VictorianFurnitureFactory(FurnitureFactory):
def create_chair(self):
return VictorianChair()
def create_coffee_table(self):
# Should return proper object
pass
def create_sofa(self):
# Should return proper object
pass
class ModernFurnitureFactory(FurnitureFactory):
def create_chair(self):
return ModernChair()
def create_coffee_table(self):
# Should return proper object
pass
def create_sofa(self):
# Should return proper object
pass