Factory Method & Abstract Factory
You'll learn to
- -Use Factory Method to defer object creation to subclasses without the caller knowing the concrete type
- -Use Abstract Factory to produce families of related objects, and explain when it earns its extra layer over a plain factory
Both patterns solve the same root problem - decoupling the code that needs an object from the code that decides which concrete class to instantiate - but at different scopes. Factory Method produces one product; Abstract Factory produces a whole family of related products that need to stay consistent with each other.
Factory Method: One Product, Deferred to Subclasses
Factory Method defines a method for creating an object, but lets subclasses decide which concrete class to instantiate. A DocumentCreator base class might declare create_document(), with PDFCreator and WordCreator subclasses each returning their own concrete Document type - callers work against DocumentCreator and never need an if/elif on document type.
class DocumentCreator(ABC):
@abstractmethod
def create_document(self) -> Document: ...
def export(self) -> None: # uses the factory method, doesn't know the concrete type
doc = self.create_document()
doc.save()
class PDFCreator(DocumentCreator):
def create_document(self) -> Document:
return PDFDocument()
class WordCreator(DocumentCreator):
def create_document(self) -> Document:
return WordDocument()Abstract Factory: Families That Must Stay Consistent
Abstract Factory earns its extra layer when you are creating several related objects that must be mutually compatible - a UI toolkit that needs a Button, Checkbox, and ScrollBar that are all either consistently "dark theme" or consistently "light theme," never a mismatched mix. A single factory interface exposes create_button(), create_checkbox(), and create_scrollbar(), and each concrete factory (DarkThemeFactory, LightThemeFactory) guarantees every product it returns belongs to the same family.
class UIFactory(ABC):
@abstractmethod
def create_button(self) -> Button: ...
@abstractmethod
def create_checkbox(self) -> Checkbox: ...
class DarkThemeFactory(UIFactory):
def create_button(self) -> Button: return DarkButton()
def create_checkbox(self) -> Checkbox: return DarkCheckbox()
class LightThemeFactory(UIFactory):
def create_button(self) -> Button: return LightButton()
def create_checkbox(self) -> Checkbox: return LightCheckbox()
def render_form(factory: UIFactory):
# can never accidentally mix a DarkButton with a LightCheckbox
button, checkbox = factory.create_button(), factory.create_checkbox()The interview tell for "do I need Abstract Factory, or is Factory Method enough": ask whether the products need to be consistent as a set. If there is only ever one product type being created, Abstract Factory's extra layer is unjustified complexity.
Interview Signal is part of Pro
See a real weak answer next to a real strong one for this exact topic.
Quiz is part of Pro
Test what you just read with a short quiz, and bank the XP.