Abstract Factory: The Third Child
The Abstract Factory pattern is a creational pattern that allows creating families of related objects without specifying their concrete classes. Instead, it defines an interface or an abstract class for creating objects and lets the sub-classes decide which classes to instantiate.
In this article, we’ll explore how to implement the Abstract Factory pattern in Python.
The Problem
Let’s consider a simple example where we want to create a GUI (Graphical User Interface) application that can run on different operating systems, such as Windows and MacOS. Each operating system has a different set of GUI components, such as buttons, labels, and text boxes.
The Solution
The Abstract Factory pattern provides a solution to this problem. We can create an abstract factory class that defines the interface for creating the different types of GUI components. We can then create separate concrete factory classes for each operating system, each of which implements the abstract factory interface and creates the corresponding set of GUI components.
Here’s how we can implement the Abstract Factory pattern in Python:
Step 1: Define the abstract factory interface.
class GUIFactory:
def create_button(self):
pass
def create_label(self):
pass
def create_text_box(self):
pass
In this step, we define an abstract GUIFactory
interface with three methods for creating different types of GUI components: create_button()
, create_label()
, and create_text_box()
. The methods are left empty as they will be implemented by the concrete factory classes.
Step 2: Create concrete factory classes.
class WindowsFactory(GUIFactory):
def create_button(self):
return WindowsButton()
def create_label(self):
return WindowsLabel()
def create_text_box(self):
return WindowsTextBox()
class MacOSFactory(GUIFactory):
def create_button(self):
return MacOSButton()
def create_label(self):
return MacOSLabel()
def create_text_box(self):
return MacOSTextBox()
In this step, we create two concrete factory classes: WindowsFactory
and MacOSFactory
. Each factory class implements the GUIFactory
interface and provides its own implementation for creating the different types of GUI components.
Step 3: Define the GUI component classes.
class Button:
def click(self):
pass
class Label:
def set_text(self, text):
pass
class TextBox:
def set_text(self, text):
pass
class WindowsButton(Button):
def click(self):
print("Windows button clicked.")
class WindowsLabel(Label):
def set_text(self, text):
print("Windows label set to: ", text)
class WindowsTextBox(TextBox):
def set_text(self, text):
print("Windows text box set to: ", text)
class MacOSButton(Button):
def click(self):
print("MacOS button clicked.")
class MacOSLabel(Label):
def set_text(self, text):
print("MacOS label set to: ", text)
class MacOSTextBox(TextBox):
def set_text(self, text):
print("MacOS text box set to: ", text)
In this step, we define the Button
, Label
, and TextBox
base classes, as well as their concrete implementations for Windows and MacOS.
Step 4: Use the abstract factory to create GUI components.
def create_gui(factory):
button = factory.create_button()
label = factory.create_label()
text_box = factory.create_text_box()
button.click()
label.set_text("Hello, world!")
text_box.set_text("This is a text box.")
# Create GUI for Windows
factory = WindowsFactory()
create_gui(factory)
# Create GUI for MacOS
Conclusion
In conclusion, the Abstract Factory pattern provides a way to create families of related objects without specifying their concrete classes. By defining an abstract factory interface and creating concrete factory classes for each family of objects, we can ensure that the objects are created consistently and correctly. This makes it easier to manage and maintain complex object hierarchies, especially when dealing with multiple platforms or systems. Overall, the Abstract Factory pattern is a powerful tool in the software engineer’s arsenal, and it’s worth considering when designing object-oriented software systems.