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.

? 25 min✓ Advanced✓ OOP basics

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

Lesson complete?

LLD basics samajh aa gayi✓ Ab Machine Coding Round seekhte hain � interview mein kaise clean code likhte hain.