Lesson 11 — Advanced
LLD: SOLID & Design Patterns
Low Level Design mein tum classes, interfaces, aur relationships design karte ho. SOLID principles aur design patterns — clean code ki foundation hain.
SOLID Principles
# S - Single Responsibility Principle
? Har class ka ek hi responsibility hona chahiye
? Bad: User class jo data bhi store karti hai aur email bhi bhejti hai
? Good: User class (data) + EmailService (email)
# O - Open/Closed Principle
? Open for extension, closed for modification
? Bad: Har naye payment type ke liye Payment class modify karo
? Good: Payment interface + CreditCardPayment, UPIPayment, etc.
# L - Liskov Substitution Principle
? Derived classes base class ko replace kar sakein
? Bad: Square class inherits Rectangle but width/height alag behave kare
? Good: Dono alag se implement karo
# I - Interface Segregation Principle
? Chhote-chhote specific interfaces banao, ek bada interface nahi
? Bad: Animal interface — fly(), swim(), walk() (sab animals nahi kar paate)
? Good: Flyable, Swimmable, Walkable interfaces
# D - Dependency Inversion Principle
? High-level modules low-level modules pe depend nahi karte
? Dono abstractions pe depend karte hain
? Bad: OrderService directly MySQL database use kare
? Good: OrderService depends on Database interface (abstraction)
Mnemonic: SOLID yaad rakho — Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion. Har principle ek specific problem solve karta hai code maintainability mein.
Creational Design Patterns
# 1. Singleton Pattern
? Ek hi instance of class exist kare
? Database connection, Logger
class Database:
_instance = None
@staticmethod
def get_instance():
if Database._instance is None:
Database._instance = Database()
return Database._instance
# 2. Factory Pattern
? Object creation logic encapsulate karo
? Client ko pata nahi kaunsi class instantiate ho rahi
class PaymentFactory:
@staticmethod
def create_payment(method):
if method == "credit_card":
return CreditCardPayment()
elif method == "upi":
return UPIPayment()
# 3. Builder Pattern
? Complex objects step-by-step build karo
? Telescoping constructor se bacho
query = (QueryBuilder()
.select("name", "email")
.from_table("users")
.where("age > 18")
.order_by("name")
.build())
Structural Design Patterns
# 1. Adapter Pattern
? Incompatible interfaces ko compatible banao
? Legacy system integrate karna ho
class OldPaymentSystem:
def make_payment_legacy(self, amt):
return f"Paid {amt}"
class PaymentAdapter:
def __init__(self, old_system):
self.old_system = old_system
def pay(self, amount):
return self.old_system.make_payment_legacy(amount)
# 2. Decorator Pattern
? Behavior dynamically add/remove karo
? Inheritance se
class Coffee:
def cost(self): return 50
class MilkDecorator:
def __init__(self, coffee):
self.coffee = coffee
def cost(self):
return self.coffee.cost() + 20
# Usage: MilkDecorator(Coffee()) — cost = 70
# 3. Proxy Pattern
? Real object ki jagah proxy use karo
? Caching, lazy loading, access control
class RealImage:
def display(self):
print("Displaying image")
class ProxyImage:
def __init__(self, filename):
self.filename = filename
self.real_image = None
def display(self):
if self.real_image is None:
self.real_image = RealImage() # lazy load
self.real_image.display()
Behavioral Design Patterns
# 1. Observer Pattern
? Ek change ho toh saare dependents ko notify karo
? Event-driven systems
class EventEmitter:
def __init__(self):
self.listeners = {}
def on(self, event, callback):
self.listeners.setdefault(event, []).append(callback)
def emit(self, event, data):
for cb in self.listeners.get(event, []):
cb(data)
# 2. Strategy Pattern
? Algorithm ka behavior runtime pe change karo
? Multiple strategies, client choose kare
class SortStrategy:
def sort(self, data): pass
class QuickSort(SortStrategy):
def sort(self, data): return quicksort(data)
class MergeSort(SortStrategy):
def sort(self, data): return mergesort(data)
class Sorter:
def __init__(self, strategy):
self.strategy = strategy
def sort(self, data):
return self.strategy.sort(data)
# 3. State Pattern
? Object ka behavior uske state ke hisaab se change
? Finite state machines
class OrderState:
def next(self, order): pass
def status(self): pass
class NewOrder(OrderState):
def next(self, order):
order.state = ProcessingOrder()
def status(self): return "New"
class ProcessingOrder(OrderState):
def next(self, order):
order.state = ShippedOrder()
def status(self): return "Processing"
Exercise
Question: SOLID mein S kya represent karta hai? (3 words)
Question: Object creation logic ko encapsulate karne wala pattern konsa hai jo client ko concrete class nahi batata? (1 word)
Common mistakes
- Over-engineering: Har cheez mein design pattern mat lagao. Simple solution pehle, pattern tab jab zaroorat ho.
- SOLID galat apply: Single Responsibility ka matlab nahi ki har method ek class mein ho. Reasonable boundaries rakho.
- Singleton overuse: Global state create karta hai, testing mushkil. Dependency injection prefer karo.
- Pattern without problem: Pehle problem samjho, phir pattern choose karo. Pattern for pattern's sake galat hai.
Lesson complete?
LLD basics samajh aa gayi? Ab Machine Coding Round seekhte hain — interview mein kaise clean code likhte hain.