Master 10 Essential Python Design Patterns with Ready-to-Run Code
This article introduces ten classic software design patterns—Singleton, Factory, Observer, Strategy, Adapter, Builder, Prototype, Decorator, Template Method, and Facade—explaining their purpose, structure, and providing complete Python code examples that demonstrate how to implement and apply each pattern in real projects.
Design patterns are reusable solutions to common software design problems. The following sections present ten widely used patterns, describe when and why to use them, and give full Python implementations that can be copied into real projects.
1. Singleton Pattern
The Singleton pattern ensures that a class has only one instance and provides a global access point to it.
class Singleton:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
# Using the singleton
instance1 = Singleton()
instance2 = Singleton()
print(instance1 is instance2) # True2. Factory Pattern
The Factory pattern separates object creation from its usage, allowing flexible instantiation of related objects.
class Product:
def operation(self):
pass
class ConcreteProduct(Product):
def operation(self):
print("ConcreteProduct operation")
class ProductFactory:
@staticmethod
def create_product():
return ConcreteProduct()
# Using the factory
product = ProductFactory.create_product()
product.operation() # "ConcreteProduct operation"3. Observer Pattern
The Observer pattern defines a one‑to‑many dependency so that when one object changes state, all its dependents are automatically notified.
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
for observer in self._observers:
observer.update()
class Observer:
def update(self):
pass
class ConcreteObserver(Observer):
def update(self):
print("ConcreteObserver received update")
subject = Subject()
observer = ConcreteObserver()
subject.attach(observer)
subject.notify() # "ConcreteObserver received update"4. Strategy Pattern
The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable.
class Strategy:
def execute(self):
pass
class ConcreteStrategyA(Strategy):
def execute(self):
print("ConcreteStrategyA execute")
class ConcreteStrategyB(Strategy):
def execute(self):
print("ConcreteStrategyB execute")
class Context:
def __init__(self, strategy):
self._strategy = strategy
def execute_strategy(self):
self._strategy.execute()
# Using the strategy
strategy_a = ConcreteStrategyA()
context = Context(strategy_a)
context.execute_strategy() # "ConcreteStrategyA execute"
strategy_b = ConcreteStrategyB()
context = Context(strategy_b)
context.execute_strategy() # "ConcreteStrategyB execute"5. Adapter Pattern
The Adapter pattern converts the interface of a class into another interface clients expect, allowing incompatible classes to work together.
class Target:
def request(self):
pass
class Adaptee:
def specific_request(self):
print("Adaptee specific request")
class Adapter(Target):
def __init__(self, adaptee):
self._adaptee = adaptee
def request(self):
self._adaptee.specific_request()
# Using the adapter
adaptee = Adaptee()
adapter = Adapter(adaptee)
adapter.request() # "Adaptee specific request"6. Builder Pattern
The Builder pattern separates the construction of a complex object from its representation, enabling the same construction process to create different representations.
class Product:
def __init__(self):
self.parts = []
def add_part(self, part):
self.parts.append(part)
def display(self):
print("Product parts:", self.parts)
class Builder:
def build_part_a(self):
pass
def build_part_b(self):
pass
def get_result(self):
pass
class ConcreteBuilder(Builder):
def __init__(self):
self.product = Product()
def build_part_a(self):
self.product.add_part("Part A")
def build_part_b(self):
self.product.add_part("Part B")
def get_result(self):
return self.product
class Director:
def construct(self, builder):
builder.build_part_a()
builder.build_part_b()
# Using the builder
builder = ConcreteBuilder()
Director().construct(builder)
product = builder.get_result()
product.display() # "Product parts: ['Part A', 'Part B']"7. Prototype Pattern
The Prototype pattern creates new objects by copying an existing object, avoiding the cost of creating objects from scratch.
import copy
class Prototype:
def clone(self):
pass
class ConcretePrototype(Prototype):
def __init__(self, value):
self.value = value
def clone(self):
return copy.deepcopy(self)
# Using the prototype
prototype = ConcretePrototype(10)
clone = prototype.clone()
print(clone.value) # 108. Decorator Pattern
The Decorator pattern dynamically adds responsibilities to objects without modifying their structure.
class Component:
def operation(self):
pass
class ConcreteComponent(Component):
def operation(self):
print("ConcreteComponent operation")
class Decorator(Component):
def __init__(self, component):
self._component = component
def operation(self):
self._component.operation()
class ConcreteDecorator(Decorator):
def operation(self):
super().operation()
self.added_behavior()
def added_behavior(self):
print("ConcreteDecorator added behavior")
# Using the decorator
component = ConcreteComponent()
decorator = ConcreteDecorator(component)
decorator.operation()
# Output:
# "ConcreteComponent operation"
# "ConcreteDecorator added behavior"9. Template Method Pattern
The Template Method pattern defines the skeleton of an algorithm in a base class, allowing subclasses to override specific steps.
class AbstractClass:
def template_method(self):
self.step1()
self.step2()
self.step3()
def step1(self):
pass
def step2(self):
pass
def step3(self):
pass
class ConcreteClass(AbstractClass):
def step2(self):
print("ConcreteClass step2")
# Using the template method
obj = ConcreteClass()
obj.template_method()
# Output:
# "AbstractClass step1"
# "ConcreteClass step2"
# "AbstractClass step3"10. Facade Pattern
The Facade pattern provides a simplified interface to a complex subsystem, hiding its internal details.
class SubsystemA:
def operation_a(self):
print("SubsystemA operation")
class SubsystemB:
def operation_b(self):
print("SubsystemB operation")
class Facade:
def __init__(self):
self._subsystem_a = SubsystemA()
self._subsystem_b = SubsystemB()
def operation(self):
self._subsystem_a.operation_a()
self._subsystem_b.operation_b()
# Using the facade
facade = Facade()
facade.operation()
# Output:
# "SubsystemA operation"
# "SubsystemB operation"These examples demonstrate how each pattern can be implemented in Python, offering a structured, maintainable, and extensible way to solve recurring design challenges.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
