Design Patterns

Compiling the learnings at one place, so that it can be very easily revised in future when needed.

Here are the top 5 most used design patterns explained simply:

Singleton
Ensures only one instance of a class exists.
Example: A single database connection shared across your app.

class Singleton:
_instance = None

def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance

a = Singleton()
b = Singleton()
print(a is b) # Output: True

Factory
Creates objects without exposing the creation logic.
Example: A button factory that makes different types of buttons (like round or square) based on input.

class Button:
def click(self):
print("Button clicked")

class RoundButton(Button):
def click(self):
print("Round button clicked")

class SquareButton(Button):
def click(self):
print("Square button clicked")

class ButtonFactory:
@staticmethod
def button_factory(shape):
if shape == "round":
return RoundButton()
elif shape == "square":
return SquareButton()
else:
return Button()

btn = ButtonFactory.button_factory("round")
btn.click() # Output: Round button clicked

Observer
Lets objects get notified when something changes in another object.
Example: News subscribers automatically get updates when new articles are published.

class NewsPublisher:
def __init__(self):
self.subscribers = []

def subscribe(self, subscriber):
self.subscribers.append(subscriber)

def notify(self, news):
for sub in self.subscribers:
sub.update(news)

class Subscriber:
def update(self, news):
print(f"Received news: {news}")

publisher = NewsPublisher()
alice = Subscriber()
publisher.subscribe(alice)
publisher.notify("New article published!") # Output: Received news: New article published!

Strategy
Lets you change the behavior of a class by switching out algorithms.
Example: Sorting data using different strategies (bubble sort, quick sort) without changing the sorting class.

class SortStrategy:
def sort(self, data):
pass

class BubbleSort(SortStrategy):
def sort(self, data):
print("Bubble sort")
return sorted(data)

class QuickSort(SortStrategy):
def sort(self, data):
print("Quick sort")
return sorted(data)

class Sorter:
def __init__(self, strategy: SortStrategy):
self.strategy = strategy

def sort(self, data):
return self.strategy.sort(data)

sorter = Sorter(BubbleSort())
sorter.sort([3, 1, 2]) # Output: Bubble sort

Decorator
Adds new features to objects without changing their structure.
Example: Wrapping a coffee object with milk or sugar decorators to add ingredients.

class Coffee:
def cost(self):
return 5

class MilkDecorator(Coffee):
def __init__(self, coffee):
self.coffee = coffee

def cost(self):
return self.coffee.cost() + 2

class SugarDecorator(Coffee):
def __init__(self, coffee):
self.coffee = coffee

def cost(self):
return self.coffee.cost() + 1

coffee = Coffee()
coffee_with_milk = MilkDecorator(coffee)
coffee_with_milk_and_sugar = SugarDecorator(coffee_with_milk)
print(coffee_with_milk_and_sugar.cost()) # Output: 8

Chain of Responsibility

Here’s the modified example where each handler’s process method calls handle of the successor (if any), and the chain is driven by calling process on the first handler:

class Handler:
def __init__(self, successor=None):
self.successor = successor

def process(self, request):
raise NotImplementedError

class ValidationHandler(Handler):
def process(self, request):
if 'data' in request and request['data']:
print("Validation passed")
if self.successor:
self.successor.process(request)
else:
print("Validation failed")
print(f"Request stopped at {self.__class__.__name__}")

class AuthenticationHandler(Handler):
def process(self, request):
if request.get('user') == 'admin':
print("Authentication passed")
if self.successor:
self.successor.process(request)
else:
print("Authentication failed")
print(f"Request stopped at {self.__class__.__name__}")

class AuthorizationHandler(Handler):
def process(self, request):
if request.get('role') == 'admin':
print("Authorization passed")
if self.successor:
self.successor.process(request)
else:
print("Authorization failed")
print(f"Request stopped at {self.__class__.__name__}")

class ProcessingHandler(Handler):
def process(self, request):
print("Request processed successfully")

# Chain setup
chain = ValidationHandler(
AuthenticationHandler(
AuthorizationHandler(
ProcessingHandler()
)
)
)

# Example request
request = {
'data': 'some important info',
'user': 'admin',
'role': 'admin'
}

chain.process(request)
# Output:
# Validation passed
# Authentication passed
# Authorization passed
# Request processed successfully

Another way

class Handler:
def __init__(self, successor=None):
self.successor = successor

def handle(self, request):
if self.process(request):
if self.successor:
self.successor.handle(request)
else:
print(f"Request stopped at {self.__class__.__name__}")

def process(self, request):
raise NotImplementedError

class ValidationHandler(Handler):
def process(self, request):
if 'data' in request and request['data']:
print("Validation passed")
return True
print("Validation failed")
return False

class AuthenticationHandler(Handler):
def process(self, request):
if request.get('user') == 'admin':
print("Authentication passed")
return True
print("Authentication failed")
return False

class AuthorizationHandler(Handler):
def process(self, request):
if request.get('role') == 'admin':
print("Authorization passed")
return True
print("Authorization failed")
return False

class ProcessingHandler(Handler):
def process(self, request):
print("Request processed successfully")
return True

# Chain setup
chain = ValidationHandler(
AuthenticationHandler(
AuthorizationHandler(
ProcessingHandler()
)
)
)

# Example request
request = {
'data': 'some important info',
'user': 'admin',
'role': 'admin'
}

chain.handle(request)
# Output:
# Validation passed
# Authentication passed
# Authorization passed
# Request processed successfully

More examples

https://github.com/pradipdharam/request-handling-with-chain-of-responsibility-pattern_machine-coding

Content was assisted/generated by GitHub Copilot, an AI programming assistant by GitHub and OpenAI. Except github links. 

Previous Post Next Post