
# Table of Contents

- **Getting Started**
  - [What is Low Level Design?](#what-is-low-level-design)
  - [LLD vs HLD](#lld-vs-hld)
  - [Types of LLD Interviews](#types-of-lld-interviews)

- **Chapter I: Object-Oriented Programming Fundamentals**
  - [Classes and Objects](#classes-and-objects)
  - [Enums](#enums)
  - [Interfaces](#interfaces)
  - [Encapsulation](#encapsulation)
  - [Abstraction](#abstraction)
  - [Inheritance](#inheritance)
  - [Polymorphism](#polymorphism)

- **Chapter II: Object Relationships and Design Principles**
  - [Association](#association)
  - [Aggregation](#aggregation)
  - [Composition](#composition)
  - [Dependency](#dependency)
  - [Realization](#realization)
  - [DRY Principle](#dry-principle)
  - [KISS Principle](#kiss-principle)
  - [YAGNI Principle](#yagni-principle)
  - [Law of Demeter](#law-of-demeter)
  - [Separation of Concerns](#separation-of-concerns)
  - [Coupling and Cohesion](#coupling-and-cohesion)
  - [Composing Objects Principle](#composing-objects-principle)

- **Chapter III: SOLID Principles**
  - [Single Responsibility Principle](#single-responsibility-principle)
  - [Open/Closed Principle](#open-closed-principle-ocp)
  - [Liskov Substitution Principle](#liskov-substitution-principle)
  - [Interface Segregation Principle](#interface-segregation-principle)
  - [Dependency Inversion Principle](#dependency-inversion-principle)

- **Chapter IV: UML Diagrams**
  - [Class Diagram](#class-diagram)
  - [Use Case Diagram](#use-case-diagram)
  - [Sequence Diagram](#sequence-diagram)
  - [Activity Diagram](#activity-diagram)

- **Chapter V: Creational Design Patterns**
  - [Introduction to Design Patterns](#introduction-to-design-patterns)
  - [Singleton Pattern](#singleton-pattern)
  - [Builder Pattern](#builder-pattern)
  - [Factory Method Pattern](#factory-method-pattern)
  - [Abstract Factory Pattern](#abstract-factory-pattern)
  - [Prototype Pattern](#prototype-pattern)

- **Chapter VI: Structural Design Patterns**
  - [Adapter Pattern](#adapter-pattern)
  - [Facade Pattern](#facade-pattern)
  - [Decorator Pattern](#decorator-pattern)
  - [Composite Pattern](#composite-pattern)
  - [Proxy Pattern](#proxy-pattern)
  - [Bridge Pattern](#bridge-pattern)
  - [Flyweight Pattern](#flyweight-pattern)

- **Chapter VII: Behavioral Design Patterns**
  - [Strategy Pattern](#strategy-pattern)
  - [Iterator Pattern](#iterator-pattern)
  - [Observer Pattern](#observer-pattern)
  - [Command Pattern](#command-pattern)
  - [State Pattern](#state-pattern)
  - [Template Method Pattern](#template-method-pattern)
  - [Chain of Responsibility Pattern](#chain-of-responsibility-pattern)
  - [Visitor Pattern](#visitor-pattern)
  - [Mediator Pattern](#mediator-pattern)
  - [Memento Pattern](#memento-pattern)

- **Chapter VIII: Additional Design Patterns**
  - [Null Object Pattern](#null-object-pattern)
  - [Repository Pattern](#repository-pattern)
  - [MVC Pattern](#mvc-pattern)
  - [Dependency Injection Pattern](#dependency-injection-pattern)
  - [Specification Pattern](#specification-pattern)
  - [Game Loop Pattern](#game-loop-pattern)
  - [Thread Pool Pattern](#thread-pool-pattern)
  - [Producer Consumer Pattern](#producer-consumer-pattern)



# What is Low Level Design?

Low Level Design (LLD) is the process of designing the internal structure and implementation details of a software system. It translates high-level architectural designs into detailed, concrete specifications that developers can directly implement in code. LLD focuses on the "how" of building software components, defining classes, methods, data structures, and their interactions.

[![What is LLD?](https://iili.io/fP7Fk11.md.png)](https://freeimage.host/i/fP7Fk11)

## Purpose of LLD

LLD serves as a blueprint for developers, providing clear guidance on:

- **Class Structure**: Defining classes, their attributes, and methods
- **Object Relationships**: Establishing how objects interact and depend on each other
- **Data Flow**: Specifying how data moves through the system
- **Algorithm Design**: Detailing the logic for complex operations
- **Interface Definitions**: Defining contracts between components

## Key Components

### 1. Class Diagrams
Visual representations showing classes, their attributes, methods, and relationships. These diagrams form the backbone of LLD documentation.

### 2. Object Models
Detailed specifications of how objects are created, managed, and destroyed throughout the system lifecycle.

### 3. Design Patterns
Reusable solutions to common software design problems, such as Singleton, Factory, or Observer patterns.

### 4. API Specifications
Clear definitions of method signatures, parameters, return types, and expected behaviors.

## LLD in the Development Process

LLD sits between High Level Design (HLD) and actual code implementation:

1. **Requirements Analysis** → Understand what to build
2. **High Level Design** → Define system architecture and components
3. **Low Level Design** → Design internal component structure
4. **Implementation** → Write the actual code
5. **Testing** → Verify the implementation

### LLD Workflow (Flowchart)
```mermaid
flowchart TD
    A[Requirements] --> B[HLD: Components & Boundaries]
    B --> C[LLD: Classes, Interfaces, Data Models]
    C --> D[Algorithms & Error Handling]
    D --> E[APIs & Contracts]
    E --> F[Implementation]
    F --> G[Unit & Integration Tests]
    G --> H[Refine Design]
    H --> C
```

## What LLD Covers

- **Classes and Objects**: Core entities and their responsibilities
- **Design Principles**: SOLID, DRY, KISS principles
- **Design Patterns**: Proven solutions for recurring problems
- **Data Structures**: Choosing appropriate data structures
- **Algorithms**: Implementing efficient logic
- **Error Handling**: Managing exceptions and edge cases
- **Code Organization**: Structuring code for maintainability

## What LLD Does Not Cover

- Infrastructure and deployment (covered in HLD)
- Network architecture and protocols
- Database scaling strategies
- Load balancing and caching strategies
- Technology stack selection

## Benefits of Good LLD

**Maintainability**: Well-designed code is easier to understand and modify

**Scalability**: Proper structure allows for easier feature additions

**Reusability**: Components can be reused across different parts of the system

**Testability**: Clear separation of concerns enables better unit testing

**Collaboration**: Provides a common understanding for team members

**Reduced Bugs**: Thoughtful design catches issues before coding begins

## LLD Documents Typically Include

- Class diagrams with detailed attributes and methods
- Sequence diagrams showing object interactions
- Pseudo-code or flowcharts for complex algorithms
- Database schema at the table/column level
- API contracts and interface definitions
- Error handling strategies

### Quick LLD Checklist
```
✅ Clear class responsibilities
✅ Interfaces separated by use-case
✅ Data models and constraints defined
✅ Algorithms documented with edge cases
✅ Failure paths and retries described
✅ Test boundaries identified
```

## When to Create LLD

LLD is particularly valuable when:

- Building complex systems with multiple interacting components
- Working in teams where clear specifications prevent miscommunication
- Creating reusable libraries or frameworks
- Dealing with intricate business logic
- Preparing for technical interviews

## LLD Best Practices

**Start Simple**: Begin with core entities and gradually add complexity

**Follow Principles**: Apply SOLID principles and design patterns appropriately

**Think Long-term**: Design for change and future requirements

**Keep it Clean**: Write self-documenting code with clear naming

**Iterate**: Refine your design based on feedback and new insights

### Common LLD Pitfalls (Avoid These)
```
❌ God classes with too many responsibilities
❌ Chatty objects with tight coupling
❌ Missing error flows (timeouts, retries, failures)
❌ Designing for one use-case only
❌ Overusing patterns without a clear need
```

Low Level Design is essential for building robust, maintainable software systems. It bridges the gap between abstract architecture and concrete implementation, ensuring that developers have a clear roadmap for bringing designs to life.


---

# LLD vs HLD

High-Level Design (HLD) and Low-Level Design (LLD) are two complementary phases in software development. Understanding their differences helps you approach system design problems effectively.

## The Fundamental Difference

**High-Level Design (HLD)** answers: "What components do we need and how do they communicate?"

**Low-Level Design (LLD)** answers: "How do we implement each component?"

Think of building a house:
- **HLD** = Architectural blueprint (rooms, plumbing, electrical layout)
- **LLD** = Construction details (how to build each door, window, wall)

## Quick Comparison

| Aspect | High-Level Design | Low-Level Design |
|--------|------------------|------------------|
| **Focus** | System architecture | Component implementation |
| **Level** | Macro (bird's eye view) | Micro (detailed view) |
| **Question** | What & Where? | How? |
| **Components** | Services, Databases, APIs | Classes, Methods, Interfaces |
| **Concerns** | Scalability, Availability | Maintainability, Testability |
| **Output** | Architecture diagrams | Class diagrams, Code structure |
| **Audience** | Architects, Stakeholders | Developers, Engineers |

## Scope Differences

### High-Level Design Covers

**System Architecture**
- Major components and their boundaries
- How services communicate with each other
- Data flow between components

**Technology Choices**
- Which databases to use (SQL vs NoSQL)
- Communication protocols (REST, gRPC, WebSockets)
- Message queues and caching layers

**Infrastructure**
- Deployment architecture
- Load balancing strategies
- CDN and storage solutions

**Non-Functional Requirements**
- Scalability (horizontal/vertical scaling)
- Availability and fault tolerance
- Performance optimization at system level
- Security and authentication mechanisms

### Low-Level Design Covers

**Code Structure**
- Classes and their responsibilities
- Interfaces and abstractions
- Object relationships and interactions

**Design Elements**
- Design patterns (Singleton, Factory, Strategy)
- SOLID principles application
- Method signatures and contracts
- Data structures and algorithms

**Implementation Details**
- How classes collaborate
- Error handling strategies
- Validation logic
- Code organization and modularity

## Visual Comparison

### HLD: E-commerce System

```text
        [Mobile App] [Web App]
              |           |
              +-----+-----+
                    |
              [API Gateway]
                    |
        +-----------+-----------+
        |           |           |
   [User        [Product    [Order
   Service]     Service]    Service]
        |           |           |
        +-----------+-----------+
                    |
            [Database Cluster]
```text

**Focus**: Services, communication, infrastructure

### LLD: Order Service

```text
    OrderController
           |
           v
    OrderService
           |
     +-----+-----+
     |     |     |
     v     v     v
  Order  Payment  Inventory
 Repository Client  Client
```text

**Focus**: Classes, methods, relationships

## Real-World Example: Notification System

### HLD Perspective

**Components**:
```text
Application --> Message Queue --> Notification Service
                                         |
                    +--------------------+--------------------+
                    |                    |                    |
                [Email API]          [SMS API]         [Push Service]
```text

**HLD Questions**:
- Which message queue? (Kafka, RabbitMQ)
- How to scale notification processing?
- How to ensure reliability?
- Which third-party providers to use?
- How to handle failures?

### LLD Perspective

**Structure**:
```text
NotificationSender (Interface)
        |
        +-- EmailSender
        +-- SmsSender
        +-- PushNotificationSender

NotificationManager
        |
        +-- uses NotificationSender implementations
        +-- routes notifications based on type
        
Notification (Entity)
        |
        +-- id, userId, message, type, status
```

**LLD Questions**:
- Which design pattern? (Strategy, Factory)
- How to structure classes?
- What are method signatures?
- How to handle validation?
- How to make it testable?

## When to Use Each

### Use HLD When

- Starting a new project
- Defining system architecture
- Choosing technology stack
- Planning for scale and growth
- Estimating infrastructure costs
- Communicating with stakeholders
- Making high-level technical decisions

### Use LLD When

- Implementing specific features
- Designing class structures
- Preparing for coding
- Writing technical documentation
- Refactoring existing code
- Conducting code reviews
- Optimizing component logic

## Interview Context

### HLD Interview

**Question**: "Design Instagram"

**Expected Discussion**:
- User service, Feed service, Media service
- Database choices for different data types
- CDN for image/video delivery
- Caching strategy for feeds
- How to handle millions of users
- Scalability and availability

**Output**: Architecture diagram showing system components

### LLD Interview

**Question**: "Design a Parking Lot System"

**Expected Discussion**:
- Key classes: ParkingLot, Vehicle, ParkingSpot, Level
- Relationships between classes
- Design patterns to use
- Method responsibilities
- How to handle different vehicle types

**Output**: Class diagram with relationships and responsibilities

## The Design Process

```text
Requirements Gathering
        ↓
High-Level Design
  • System components
  • Technology choices
  • Infrastructure planning
        ↓
Low-Level Design
  • Class design
  • Method definitions
  • Design patterns
        ↓
Implementation
        ↓
Testing & Deployment
```javascript

## Key Characteristics

### HLD Characteristics

**Abstraction Level**: High - focuses on big picture

**Granularity**: Coarse-grained components

**Changes Impact**: Affects entire system

**Documentation**: System architecture documents, component diagrams

**Typical Diagrams**: Architecture diagrams, deployment diagrams, data flow diagrams

### LLD Characteristics

**Abstraction Level**: Low - focuses on implementation details

**Granularity**: Fine-grained classes and methods

**Changes Impact**: Affects specific components

**Documentation**: API documentation, class diagrams, sequence diagrams

**Typical Diagrams**: Class diagrams, sequence diagrams, object diagrams

## Complementary Nature

HLD and LLD work together:

```text
HLD defines: "We need an Order Processing System"
        ↓
    Components:
    - Order Service
    - Payment Service
    - Inventory Service
        ↓
LLD defines: "How to implement Order Service"
        ↓
    Classes:
    - OrderController
    - OrderService
    - OrderRepository
    - Order (Entity)
```text

**HLD provides the roadmap**
**LLD provides the implementation blueprint**

## Common Mistakes

### HLD Mistakes
- Over-engineering for current needs
- Not considering failure scenarios
- Ignoring network latency and costs
- Single point of failure
- Wrong technology choices

### LLD Mistakes
- Violating SOLID principles
- Creating monolithic classes
- Tight coupling between components
- Poor naming conventions
- Ignoring design patterns
- Not considering testability

## Summary

**High-Level Design**:
- System-level thinking
- What to build and where
- Architecture and infrastructure
- Services and their interactions
- Scalability and availability

**Low-Level Design**:
- Component-level thinking
- How to build each piece
- Classes and their relationships
- Design patterns and principles
- Code quality and maintainability

**Both are essential**: HLD gives direction, LLD gives structure. Master both to become a well-rounded software engineer.

---

# Types of LLD Interviews

Low-Level Design interviews come in different formats, each testing specific aspects of your design and coding skills. Understanding these types helps you prepare effectively and know what to expect.

## Overview of Interview Types

| Type | Focus | Format | Duration |
|------|-------|--------|----------|
| **Object-Oriented Design** | Class structure, relationships | Whiteboard/Discussion | 45-60 min |
| **Machine Coding** | Working implementation | IDE/Editor | 60-90 min |
| **Concurrency Design** | Thread safety, synchronization | Code + Discussion | 45-60 min |
| **API Design** | Interface contracts | Discussion/Design doc | 30-45 min |
| **Schema Design** | Database structure | Diagram/Discussion | 30-45 min |

## 1. Object-Oriented Design Interview

### What It Tests
- Understanding of OOP principles
- Class design and relationships
- Design pattern knowledge
- System modeling skills

### Format
```text
Question → Discussion → Class Diagram → Design Review
```

### Typical Flow

**Step 1: Problem Statement**
- Interviewer gives you a problem (e.g., "Design a Library Management System")

**Step 2: Clarify Requirements**
- Ask questions about scope and constraints
- Identify core functionalities
- Understand user interactions

**Step 3: Identify Entities**
- List main classes (Book, Member, Librarian)
- Define responsibilities for each class

**Step 4: Design Relationships**
- Association, composition, inheritance
- One-to-many, many-to-many relationships

**Step 5: Apply Design Patterns**
- Choose appropriate patterns
- Justify your choices

### Example Questions
- Design a parking lot system
- Design an elevator system
- Design a chess game
- Design a hotel booking system
- Design a movie ticket booking system

### What Interviewers Look For
- Clear class responsibilities (Single Responsibility Principle)
- Proper use of inheritance and interfaces
- Understanding of relationships between objects
- Appropriate design pattern usage
- Extensibility and maintainability

### Common Mistakes
- Creating God classes (too many responsibilities)
- Over-engineering simple problems
- Not asking clarifying questions
- Ignoring SOLID principles
- Poor naming conventions

## 2. Machine Coding Interview

### What It Tests
- Ability to write working code quickly
- Code organization and structure
- Problem-solving under time pressure
- Clean code practices

### Format
```text
Problem → Code Implementation → Demo → Code Review
```text

### Typical Setup
- You get access to an IDE or online editor
- 60-90 minutes to implement the solution
- Must produce runnable code
- Code should handle edge cases

### Characteristics
- **Time-bound**: Strict deadlines
- **Fully functional**: Code must run without errors
- **Clean code**: Readable and well-structured
- **Testing**: Include basic test cases

### Example Questions
- Implement a Tic-Tac-Toe game
- Build a simple in-memory database
- Create a rate limiter
- Implement a URL shortener
- Design and code a basic calculator

### What Interviewers Look For
- Working solution within time limit
- Code modularity and organization
- Error handling
- Edge case coverage
- Clean, readable code with good naming

### Common Mistakes
- Spending too much time on perfect design
- Not testing code before submitting
- Ignoring edge cases
- Poor time management
- Writing messy, unreadable code

## 3. Concurrency Design Interview

### What It Tests
- Understanding of multi-threading concepts
- Thread safety and synchronization
- Race condition handling
- Deadlock prevention

### Format
```text
Problem → Identify Concurrency Issues → Design Solution → Implementation
```

### Key Concepts Tested
- **Thread Safety**: Ensuring data consistency
- **Synchronization**: Coordinating multiple threads
- **Race Conditions**: Preventing concurrent access issues
- **Deadlocks**: Avoiding circular dependencies
- **Locking Mechanisms**: Mutexes, semaphores, read-write locks

### Example Questions
- Design a thread-safe singleton
- Implement a producer-consumer pattern
- Design a thread pool
- Create a concurrent queue
- Implement a dining philosophers solution

### What Interviewers Look For
- Identification of critical sections
- Proper use of locks and synchronization
- Understanding of thread lifecycle
- Knowledge of concurrent data structures
- Deadlock avoidance strategies

### Common Mistakes
- Not identifying race conditions
- Over-synchronization (performance issues)
- Creating potential deadlocks
- Not understanding thread safety guarantees
- Ignoring atomic operations

## 4. API Design Interview

### What It Tests
- RESTful design principles
- Interface design skills
- Understanding of HTTP methods
- API versioning and documentation

### Format
```text
Requirements → Design Endpoints → Define Contracts → Discuss Trade-offs
```text

### Key Focus Areas

**Endpoint Design**
- Proper URL structure
- Resource naming conventions
- HTTP method usage (GET, POST, PUT, DELETE)

**Request/Response Format**
- JSON structure
- Error handling
- Status codes

**API Features**
- Pagination
- Filtering and sorting
- Authentication and authorization
- Rate limiting

### Example Questions
- Design REST API for a social media platform
- Design API for an e-commerce system
- Create API for a ride-sharing app
- Design API for a food delivery service

### What Interviewers Look For
- RESTful best practices
- Proper resource naming
- Appropriate HTTP status codes
- Error response structure
- Versioning strategy
- Documentation clarity

### Common Mistakes
- Inconsistent naming conventions
- Improper HTTP method usage
- Not considering pagination
- Poor error handling design
- Ignoring authentication/authorization

## 5. Schema Design Interview

### What It Tests
- Database modeling skills
- Understanding of relationships
- Normalization knowledge
- Query optimization awareness

### Format
```text
Requirements → Identify Entities → Define Relationships → Optimize
```

### Key Components

**Tables and Columns**
- Entity identification
- Attribute definition
- Data types selection

**Relationships**
- One-to-one
- One-to-many
- Many-to-many

**Constraints**
- Primary keys
- Foreign keys
- Unique constraints
- Check constraints

**Optimization**
- Indexing strategy
- Normalization vs denormalization
- Query performance

### Example Questions
- Design database schema for Twitter
- Create schema for an e-commerce platform
- Design tables for a hospital management system
- Schema for a learning management system

### What Interviewers Look For
- Proper entity identification
- Correct relationship modeling
- Appropriate indexing
- Normalization understanding
- Scalability considerations

### Common Mistakes
- Over-normalization or under-normalization
- Missing indexes on foreign keys
- Incorrect relationship types
- Not considering query patterns
- Ignoring data integrity constraints

## Preparation Strategy

### For Object-Oriented Design
- Practice drawing class diagrams
- Study design patterns thoroughly
- Review SOLID principles
- Practice explaining your design choices

### For Machine Coding
- Practice coding under time pressure
- Use online coding platforms
- Focus on clean code practices
- Build small projects regularly

### For Concurrency Design
- Study multithreading concepts
- Understand synchronization primitives
- Practice concurrent programming problems
- Learn common patterns (Producer-Consumer, Thread Pool)

### For API Design
- Study REST principles
- Review HTTP methods and status codes
- Practice designing endpoints
- Look at real-world API examples

### For Schema Design
- Practice ER diagram creation
- Study normalization forms
- Understand indexing strategies
- Review real database schemas

## Interview Tips

**Before the Interview**:
- Clarify which type of LLD interview to expect
- Prepare accordingly based on the format
- Practice similar problems
- Review fundamental concepts

**During the Interview**:
- Ask clarifying questions upfront
- Think out loud
- Start simple, then iterate
- Consider edge cases
- Discuss trade-offs

**Common Across All Types**:
- Clear communication
- Structured thinking
- Justifying design decisions
- Time management
- Handling feedback gracefully

## Summary

Different LLD interview types test different skills:

- **Object-Oriented Design**: Tests your ability to model systems using classes
- **Machine Coding**: Tests implementation speed and code quality
- **Concurrency Design**: Tests understanding of multi-threading
- **API Design**: Tests interface design and REST principles
- **Schema Design**: Tests database modeling skills

Know which type you're facing and prepare accordingly. Often, interviews combine multiple types to get a comprehensive view of your skills.

---

# Classes and Objects

Classes and objects are the core building blocks of Object-Oriented Programming. A class defines structure and behavior, while an object is a concrete instance with its own state.

## What is a Class?

A **class** is a blueprint or template that defines the structure and behavior of objects.

Think of a class as a **recipe**:
- The ingredients are attributes (data/properties)
- The cooking steps are methods (actions/functions)
- The recipe itself isn't a cake—it just tells you how to make one

### Class Components
```text
┌─────────────────────────┐
│       Class Name        │
├─────────────────────────┤
│ Attributes (Data)       │
│ - property1             │
│ - property2             │
├─────────────────────────┤
│ Methods (Actions)       │
│ + action1()             │
│ + action2()             │
└─────────────────────────┘
```text

**Example: Car Class**
```javascript
Class: Car
----------
Attributes:
- brand
- model
- speed

Methods:
+ startEngine()
+ accelerate()
+ brake()
```sql

The `Car` class describes what any car should have and what it can do, but it's not an actual car yet.

## What is an Object?

An **object** is an actual instance created from a class. It's a real thing with its own data that you can use and interact with.

Using our recipe analogy:
- **Class** = The recipe
- **Object** = The actual cake you bake

### Creating Objects from a Class
```javascript
        ┌─────────────┐
        │ Class: Car  │ (Blueprint)
        └──────┬──────┘
               │
        Creates instances
               │
     ┌─────────┼─────────┐
     │         │         │
     ▼         ▼         ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│  car1   │ │  car2   │ │  car3   │
│ Toyota  │ │  Ford   │ │  BMW    │
│ 50 km/h │ │ 80 km/h │ │ 0 km/h  │
└─────────┘ └─────────┘ └─────────┘
```text

### Class → Object Flow
```mermaid
flowchart LR
  A[Class Definition] --> B[Constructor]
  B --> C[Object Instance]
  C --> D[Methods + State]
```

Each object has:
- Its own unique data (different brands and speeds)
- The same structure (all have brand, model, speed)
- The same capabilities (all can accelerate, brake)

## Simple Example: Student System

**Class Definition**:
```javascript
Class: Student
--------------
Attributes:
- rollNumber
- name
- marks

Methods:
+ study()
+ takeExam()
+ getGrade()
```

**Creating Objects**:
```text
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│ student1        │  │ student2        │  │ student3        │
├─────────────────┤  ├─────────────────┤  ├─────────────────┤
│ rollNo: 101     │  │ rollNo: 102     │  │ rollNo: 103     │
│ name: "Alice"   │  │ name: "Bob"     │  │ name: "Carol"   │
│ marks: 95       │  │ marks: 87       │  │ marks: 92       │
└─────────────────┘  └─────────────────┘  └─────────────────┘
```text

## Class vs Object

| Class | Object |
|-------|--------|
| Blueprint/Template | Actual instance |
| Defined once | Created many times |
| No memory used | Uses memory |
| Recipe | Cake |
| House plan | Actual house |

## How They Work Together
```text
Step 1: Define a Class
        ↓
Step 2: Create Objects from that Class
        ↓
Step 3: Each Object gets its own data
        ↓
Step 4: Objects use methods from the Class
```text

## Real Example: Bank Account

**The Class**:
```javascript
┌──────────────────────┐
│ Class: BankAccount   │
├──────────────────────┤
│ - accountNumber      │
│ - holderName         │
│ - balance            │
├──────────────────────┤
│ + deposit()          │
│ + withdraw()         │
│ + checkBalance()     │
└──────────────────────┘
```text

**The Objects**:
```
account1                account2                account3
- Acc: 1001            - Acc: 1002            - Acc: 1003
- Name: John           - Name: Sarah          - Name: Mike
- Balance: $5000       - Balance: $3000       - Balance: $7500
```javascript

When John deposits $500, only `account1` balance changes. Sarah's and Mike's accounts remain unaffected.

## Key Points

**Classes**:
- Are templates that define structure
- Contain attributes (data) and methods (actions)
- Don't hold actual data themselves

**Objects**:
- Are created from classes
- Have their own independent data
- Can perform actions defined in the class
- Multiple objects can exist from one class

**Relationship**:
- One class → Many objects
- Each object operates independently
- All objects share the same structure and methods

## Why Use Classes and Objects?

**Organization**: Group related data and behavior together

**Reusability**: Write the class once, create many objects

**Independence**: Each object maintains its own state

**Real-world Modeling**: Represent entities like users, products, orders

## Summary

Think of it simply:
- **Class** = Cookie cutter (the shape/template)
- **Object** = Individual cookies (actual items)

The class defines "what" things should look like and "what" they can do. Objects are the actual "things" you work with, each having its own data but sharing the same capabilities.

---

# Enums

Enums (enumerations) represent a fixed set of named constants. They make your code clearer and safer by limiting values to predefined options.

## What is an Enum?

An **enum** is a collection of related constant values grouped together.

**Simple rule**: If a variable can only be one of a few specific values, use an enum.

## Why Use Enums?

**Avoid Magic Values**: No more mysterious strings like `"pending"` or numbers like `2`

**Readability**: `OrderStatus.SHIPPED` is clearer than `"shipped"`

**Type Safety**: Prevents invalid values and typos

**Maintainability**: Change values in one place

**IDE Support**: Auto-completion and error detection

## Common Use Cases

```text
Order Status          User Roles           Payment Methods
├─ PENDING           ├─ ADMIN             ├─ CREDIT_CARD
├─ CONFIRMED         ├─ CUSTOMER          ├─ DEBIT_CARD
├─ SHIPPED           ├─ MANAGER           ├─ UPI
├─ DELIVERED         └─ GUEST             └─ CASH
└─ CANCELLED
```javascript

## Basic Example

### Without Enum (Bad)

```javascript
let status = "shipped";

// Easy to make typos
if (status === "shippd") {  // Bug!
    console.log("Shipped");
}

// Can assign anything
status = "random_value";  // No error!
```

### With Enum (Good)

```javascript
const OrderStatus = {
    PENDING: "PENDING",
    CONFIRMED: "CONFIRMED",
    SHIPPED: "SHIPPED",
    DELIVERED: "DELIVERED",
    CANCELLED: "CANCELLED"
};

Object.freeze(OrderStatus);

let status = OrderStatus.SHIPPED;

if (status === OrderStatus.SHIPPED) {
    console.log("Order is on the way");
}
```javascript

## Enum with Properties

Enums can hold additional data and behavior.

```javascript
const PaymentMethod = {
    CREDIT_CARD: { 
        name: "Credit Card", 
        fee: 2.5 
    },
    DEBIT_CARD: { 
        name: "Debit Card", 
        fee: 1.5 
    },
    UPI: { 
        name: "UPI", 
        fee: 0 
    }
};

Object.freeze(PaymentMethod);

// Usage
function calculateTotal(amount, method) {
    const fee = (amount * method.fee) / 100;
    return amount + fee;
}

const total = calculateTotal(1000, PaymentMethod.CREDIT_CARD);
console.log(`Total: ₹${total}`);  // ₹1025
```javascript

## Real Example: Traffic Light

```javascript
const TrafficLight = {
    RED: { 
        action: "STOP", 
        duration: 60 
    },
    YELLOW: { 
        action: "PREPARE", 
        duration: 5 
    },
    GREEN: { 
        action: "GO", 
        duration: 45 
    }
};

Object.freeze(TrafficLight);

let current = TrafficLight.RED;
console.log(`Action: ${current.action}`);  // STOP
console.log(`Wait: ${current.duration}s`); // 60s
```javascript

## Best Practices

### Use Clear Names

```javascript
// Good
const OrderStatus = { PENDING, SHIPPED };

// Bad
const Status = { S1, S2 };
```javascript

### Always Freeze

```javascript
Object.freeze(OrderStatus);  // Prevent changes
```

### Group Related Values

```javascript
// Good
const OrderStatus = { PENDING, SHIPPED };
const PaymentStatus = { PAID, UNPAID };

// Bad
const Status = { ORDER_PENDING, PAYMENT_PAID };
```javascript

## Common Patterns

**Status Tracking**:

```javascript
const TaskStatus = {
    TODO: "TODO",
    IN_PROGRESS: "IN_PROGRESS",
    DONE: "DONE"
};
```javascript

**User Roles**:

```javascript
const UserRole = {
    ADMIN: "ADMIN",
    EDITOR: "EDITOR",
    VIEWER: "VIEWER"
};
```javascript

**Priority Levels**:

```javascript
const Priority = {
    LOW: { level: 1 },
    MEDIUM: { level: 2 },
    HIGH: { level: 3 }
};
```javascript

## When NOT to Use Enums

- Values change frequently
- List is dynamic or user-defined
- Values are unique per user
- Need unlimited options

## Summary

**Enums** define fixed sets of constants for better code clarity

**Use enums** instead of strings/numbers to avoid errors

**Always freeze** enums to prevent modifications

**Add properties** to enums for richer functionality

Think of enums as a dropdown menu—only the listed options are valid.

---



# Interfaces

Interfaces define contracts that specify what a class should do, without dictating how it should do it. They are the foundation of flexible and maintainable object-oriented design.

## What is an Interface?

An **interface** is a contract that lists methods a class must implement. It defines behavior without providing implementation.

**Key Rule**: Interface defines the "what", classes provide the "how"

### Real-World Analogy

Think of a **remote control**:

```
Remote Control (Interface)
├─ play()
├─ pause()
├─ volumeUp()
└─ powerOff()

Works with any device:
├─ TV
├─ Soundbar
└─ Projector
```text

The remote doesn't care which device it controls—as long as the device understands the commands (implements the interface).

## Why Use Interfaces?

**Define Behavior**: Specify required methods, not their implementation

**Enable Flexibility**: Multiple classes can implement the same interface differently

**Loose Coupling**: Code depends on contracts, not specific implementations

**Easy Testing**: Create mock implementations for tests

**Extensibility**: Add new implementations without changing existing code

## Visual Understanding

### Without Interface (Tight Coupling)
```text
CheckoutService
     ↓ (hardcoded dependency)
StripePayment

Problem: Can't easily switch or test
```

### With Interface (Loose Coupling)
```text
CheckoutService
     ↓ (depends on contract)
PaymentGateway (Interface)
     ↓
┌────┼────┐
↓    ↓    ↓
Stripe PayPal Razorpay

Benefit: Easy to switch, test, extend
```javascript

## Simple Example

### Without Interface
```javascript
class CheckoutService {
    checkout(amount) {
        const stripe = new StripePayment();
        stripe.process(amount);  // Tightly coupled to Stripe
    }
}
```javascript

**Problems**: Hard to test, can't switch providers, inflexible

### With Interface
```javascript
// Interface (contract)
class PaymentGateway {
    processPayment(amount) {
        throw new Error("Must implement processPayment()");
    }
}

// Implementations
class StripePayment extends PaymentGateway {
    processPayment(amount) {
        console.log(`Stripe: $${amount}`);
    }
}

class RazorpayPayment extends PaymentGateway {
    processPayment(amount) {
        console.log(`Razorpay: ₹${amount}`);
    }
}

// Service depends on interface
class CheckoutService {
    constructor(gateway) {
        this.gateway = gateway;
    }
    
    checkout(amount) {
        this.gateway.processPayment(amount);
    }
}

// Easy to switch
const service = new CheckoutService(new StripePayment());
service.checkout(100);  // Stripe: $100

service.gateway = new RazorpayPayment();
service.checkout(100);  // Razorpay: ₹100
```text

**Benefits**: Flexible, testable, extensible

## How Interfaces Work

```
Step 1: Define Interface
    Interface declares methods
         ↓
Step 2: Classes Implement Interface
    Each class provides its own logic
         ↓
Step 3: Code Uses Interface
    Works with any implementation
         ↓
Step 4: Switch Implementations
    Change behavior without changing code
```text

## Common Use Cases

**Payment Processing**
```text
PaymentGateway Interface
├─ Stripe
├─ PayPal
└─ Razorpay
```text

**Notifications**
```
NotificationSender Interface
├─ EmailSender
├─ SmsSender
└─ PushSender
```text

**Data Storage**
```text
Database Interface
├─ MySQLDatabase
├─ PostgreSQLDatabase
└─ MongoDBDatabase
```text

**Authentication**
```
AuthProvider Interface
├─ OAuthProvider
├─ JWTProvider
└─ SessionProvider
```text

## Key Benefits

| Without Interface | With Interface |
|------------------|----------------|
| Tight coupling | Loose coupling |
| Hard to test | Easy to test |
| Hard to extend | Easy to extend |
| Rigid | Flexible |
| Changes break code | Changes isolated |

## Real-World Scenario

**Problem**: E-commerce site needs to support multiple payment methods

**Solution with Interface**:
```text
1. Define: PaymentGateway interface
2. Implement: Stripe, PayPal, Razorpay classes
3. Use: CheckoutService works with any gateway
4. Result: Add new payment methods anytime
```text

## Best Practices

**Keep It Simple**: Only include necessary methods

**Clear Naming**: Use descriptive names (`PaymentGateway`, not `PG`)

**Single Purpose**: One interface, one responsibility

**Program to Interface**: Depend on interfaces, not concrete classes

## Summary

**Interfaces** are contracts defining required methods

**Enable polymorphism** - different implementations, same interface

**Promote loose coupling** - code depends on contracts, not implementations

**Make systems flexible** - easy to switch, test, and extend

Think of interfaces as **universal adapters** - any device that fits the adapter can be plugged in.

---


# Encapsulation

Encapsulation is the practice of bundling data and methods that operate on that data within a single unit (class), while hiding internal details and exposing only what's necessary.

## What is Encapsulation?

**Encapsulation** means wrapping data and the methods that work on that data together, while restricting direct access to some components.

**Core Idea**: Hide internal details, expose only what's needed

Think of a **car**:
- You use the steering wheel, pedals, and gear shift (public interface)
- You don't directly touch the engine, transmission, or fuel injection (private internals)

## Why Use Encapsulation?

**Data Protection**: Prevent unauthorized or accidental modification

**Controlled Access**: Use methods to validate and control how data is changed

**Flexibility**: Change internal implementation without affecting external code

**Maintainability**: Changes to internals don't break other parts of the system

**Reduced Complexity**: Users only see what they need to see

## Key Concepts

### Access Modifiers

```sql
Public (+)
└─ Accessible from anywhere

Private (-)
└─ Accessible only within the class

Protected (#)
└─ Accessible within class and subclasses
```text

### Information Hiding

```
┌─────────────────────────┐
│      BankAccount        │
├─────────────────────────┤
│ - balance (private)     │ ← Hidden
│ - accountNumber         │ ← Hidden
├─────────────────────────┤
│ + deposit() (public)    │ ← Exposed
│ + withdraw() (public)   │ ← Exposed
│ + getBalance() (public) │ ← Exposed
└─────────────────────────┘

Users can only interact through public methods
```text

## Simple Example

### Without Encapsulation (Bad)

```javascript
class BankAccount {
    constructor() {
        this.balance = 0;  // Public - anyone can modify
    }
}

const account = new BankAccount();
account.balance = 1000000;  // Direct access - dangerous!
account.balance = -500;     // Invalid state - no validation!
```bash

**Problems**: No validation, no control, data can be corrupted

### With Encapsulation (Good)

```javascript
class BankAccount {
    #balance;  // Private field
    
    constructor() {
        this.#balance = 0;
    }
    
    deposit(amount) {
        if (amount > 0) {
            this.#balance += amount;
            return true;
        }
        return false;  // Validation
    }
    
    withdraw(amount) {
        if (amount > 0 && amount <= this.#balance) {
            this.#balance -= amount;
            return true;
        }
        return false;  // Validation
    }
    
    getBalance() {
        return this.#balance;  // Read-only access
    }
}

const account = new BankAccount();
account.deposit(1000);
account.withdraw(200);
console.log(account.getBalance());  // 800

// account.#balance = 5000;  // Error! Can't access private field
```text

**Benefits**: Validation, controlled access, data integrity

## Real-World Example

```
class User {
    #password;  // Private
    
    constructor(username, password) {
        this.username = username;
        this.#password = this.#hashPassword(password);
    }
    
    #hashPassword(password) {
        // Hash password (private method)
        return `hashed_${password}`;
    }
    
    verifyPassword(password) {
        return this.#password === this.#hashPassword(password);
    }
    
    // No direct access to password
}

const user = new User("john", "secret123");
console.log(user.verifyPassword("secret123"));  // true
// console.log(user.#password);  // Error! Private field
```text

## Benefits Summary

```java
┌────────────────────────────────────────┐
│     Benefits of Encapsulation          │
└────────────────────────────────────────┘

Data Protection
└─ Prevent invalid states

Controlled Access
└─ Validation before modification

Flexibility
└─ Change internals without breaking code

Maintainability
└─ Reduce dependencies

Security
└─ Hide sensitive information
```javascript

## Key Takeaways

- **Bundle data and methods** that operate on that data
- **Hide internal details** using private fields/methods
- **Expose only necessary parts** through public methods
- **Validate and control** data access and modification
- **Protect data integrity** by preventing direct access

---

# Abstraction

Abstraction is the practice of hiding complex implementation details and showing only the essential features of an object. It focuses on "what" an object does rather than "how" it does it.

## What is Abstraction?

**Abstraction** means exposing only relevant information while hiding unnecessary complexity.

**Core Idea**: Show what matters, hide how it works

Think of a **coffee machine**:
- You press a button to get coffee (simple interface)
- Internal processes (grinding beans, heating water, brewing) are hidden

## Abstraction vs Encapsulation

```text
Encapsulation                  Abstraction
├─ Data hiding                 ├─ Complexity hiding
├─ Bundles data & methods      ├─ Shows essential features
├─ Implementation detail       ├─ Design level concept
└─ How to hide                 └─ What to hide
```

**Encapsulation**: Hide data using access modifiers  
**Abstraction**: Hide complexity using interfaces/abstract classes

## Why Use Abstraction?

**Simplicity**: Users work with simple interfaces, not complex implementations

**Reduced Complexity**: Focus on what matters, ignore details

**Flexibility**: Change implementation without affecting users

**Maintainability**: Easier to understand and modify

## Simple Example

### Without Abstraction

```javascript
class EmailService {
    sendEmail(to, subject, body) {
        // User must know all these details
        const connection = this.connectToServer();
        const auth = this.authenticate();
        const formatted = this.formatMessage(to, subject, body);
        const encrypted = this.encryptMessage(formatted);
        this.sendToSMTP(connection, encrypted);
        this.closeConnection(connection);
    }
}
```javascript

**Problem**: User must understand the entire process

### With Abstraction

```javascript
class EmailService {
    send(to, subject, body) {
        // Simple interface - complexity hidden
        this.#process(to, subject, body);
    }
    
    #process(to, subject, body) {
        // All complexity hidden in private method
        // Connection, authentication, formatting, etc.
    }
}

// Usage - simple and clean
const email = new EmailService();
email.send("user@example.com", "Hello", "Message");
```javascript

**Benefit**: User only needs to know `send()`, not the internal steps

## Real-World Example: Payment System

```javascript
// Abstract the payment process
class PaymentProcessor {
    processPayment(amount, method) {
        // High-level interface
        this.#validatePayment(amount);
        this.#initiateTransaction(amount, method);
        this.#sendConfirmation();
        return { success: true, transactionId: "TXN123" };
    }
    
    // Hide complex implementation
    #validatePayment(amount) { /* validation logic */ }
    #initiateTransaction(amount, method) { /* transaction logic */ }
    #sendConfirmation() { /* notification logic */ }
}

// User doesn't need to know the details
const processor = new PaymentProcessor();
processor.processPayment(100, "card");  // Simple!
```

## Levels of Abstraction

```text
High Level (Abstract)
    ↓
user.login()
    ↓
authenticateUser()
    ↓
validateCredentials()
    ↓
hashPassword()
    ↓
compareHashes()
    ↓
Low Level (Concrete)
```text

Higher levels hide complexity from lower levels.

## Benefits Summary

```text
┌────────────────────────────────────────┐
│      Benefits of Abstraction           │
└────────────────────────────────────────┘

Simplicity
└─ Simple interfaces for complex operations

Focus
└─ Work with essential features only

Flexibility
└─ Change implementation freely

Reusability
└─ Abstract components are more reusable

Maintainability
└─ Easier to understand and modify
```sql

## Key Takeaways

- **Hide complexity**, expose simplicity
- **Focus on "what"**, not "how"
- **Provide simple interfaces** for complex operations
- **Different from encapsulation** but often used together
- **Makes code easier to use** and understand

---

# Inheritance

Inheritance is a mechanism where a new class (child/subclass) derives properties and behaviors from an existing class (parent/superclass). It promotes code reuse and establishes hierarchical relationships.

## What is Inheritance?

**Inheritance** allows a class to inherit attributes and methods from another class.

**Core Idea**: Child class gets parent's features + can add its own

Think of **family traits**:
- Children inherit traits from parents (eye color, height)
- But also have their own unique characteristics

## Why Use Inheritance?

**Code Reuse**: Don't repeat common code in multiple classes

**Hierarchy**: Model real-world relationships (is-a relationships)

**Extensibility**: Add new features to existing classes

**Maintainability**: Update common behavior in one place

## Basic Structure
```text
┌─────────────────┐
│  Parent Class   │
│  (Superclass)   │
├─────────────────┤
│ + commonMethod()│
└────────┬────────┘
         │ inherits
         ↓
┌─────────────────┐
│  Child Class    │
│  (Subclass)     │
├─────────────────┤
│ + commonMethod()│ ← Inherited
│ + newMethod()   │ ← New feature
└─────────────────┘
```javascript

## Simple Example
```javascript
// Parent class
class Animal {
    constructor(name) {
        this.name = name;
    }
    
    eat() {
        console.log(`${this.name} is eating`);
    }
    
    sleep() {
        console.log(`${this.name} is sleeping`);
    }
}

// Child class inherits from Animal
class Dog extends Animal {
    bark() {
        console.log(`${this.name} is barking`);
    }
}

const dog = new Dog("Buddy");
dog.eat();    // Inherited from Animal
dog.bark();   // Dog's own method
```

## Inheritance Hierarchy
```javascript
        Animal
       /      \
      /        \
    Dog       Cat
    /  \
   /    \
Bulldog Labrador
```javascript

Each level inherits from the one above it.

## Types of Inheritance

### 1. Single Inheritance

One child class inherits from one parent class.
```sql
    Parent
      ↓
    Child
    
Example: Vehicle → Car
```javascript

**Use Case**: Simple parent-child relationship

### 2. Multilevel Inheritance

A class inherits from a child class, forming a chain.
```text
   Parent
     ↓
   Child
     ↓
 Grandchild
 
Example: Vehicle → Car → SportsCar
```

**Use Case**: Deep hierarchical relationships with multiple levels of specialization

### 3. Hierarchical Inheritance

Multiple child classes inherit from the same parent class.
```javascript
      Parent
      /    \
     /      \
  Child1  Child2
  
Example: Animal → Dog, Cat, Bird
```javascript

**Use Case**: Multiple variations of the same base concept

### 4. Multiple Inheritance

A child class inherits from multiple parent classes.
```sql
  Parent1   Parent2
       \     /
        \   /
        Child
        
Example: FlyingFish inherits from Fish and Bird
```text

**Note**: Not all languages support this directly due to complexity (diamond problem). Languages handle this differently - some support it (C++, Python), some don't (Java, JavaScript), and some use interfaces/traits instead.

### 5. Hybrid Inheritance

Combination of two or more types of inheritance.
```
       A
      / \
     B   C
      \ /
       D
```text

**Use Case**: Complex domain models requiring multiple inheritance patterns

## Method Overriding

Child classes can override parent methods to provide specific behavior.
```javascript
class Vehicle {
    start() {
        console.log("Vehicle starting...");
    }
}

class Car extends Vehicle {
    start() {
        console.log("Car engine starting...");  // Override
    }
}

const car = new Car();
car.start();  // Car engine starting...
```

## When to Use Inheritance

**Use When**:
- Clear "is-a" relationship (Dog is an Animal)
- Shared behavior across classes
- Need to extend existing functionality

**Avoid When**:
- No clear hierarchical relationship
- Composition would be simpler
- Creates tight coupling

## Benefits and Drawbacks
```javascript
Benefits                    Drawbacks
├─ Code reuse              ├─ Tight coupling
├─ Logical hierarchy       ├─ Fragile base class
├─ Easy maintenance        ├─ Deep hierarchies
└─ Polymorphism support    └─ Less flexible than composition
```javascript

## Key Takeaways

- **Child class inherits** parent's properties and methods
- **Establishes "is-a"** relationships
- **Multiple types exist**: single, multilevel, hierarchical, multiple, hybrid
- **Override methods** for specific behavior
- **Balance** between reuse and flexibility

---

# Polymorphism

Polymorphism allows objects of different classes to be treated as objects of a common parent class. It enables one interface to be used for different data types or classes.

## What is Polymorphism?

**Polymorphism** means "many forms" - the ability of different objects to respond to the same method call in their own way.

**Core Idea**: Same interface, different behaviors

Think of a **shape**:
- All shapes can be drawn
- Circle, Square, Triangle draw themselves differently
- Same method (`draw()`), different implementations

## Why Use Polymorphism?

**Flexibility**: Write code that works with multiple types

**Extensibility**: Add new types without changing existing code

**Simplicity**: Use common interfaces for different objects

**Maintainability**: Easier to manage and extend

## Visual Understanding
```text
        Shape
          ↓
    draw() method
          ↓
    ┌─────┼─────┐
    ↓     ↓     ↓
Circle Square Triangle
    ↓     ↓     ↓
  draws draws draws
  circle square triangle
```

Same method name, different behavior for each shape.

## Simple Example
```javascript
class Animal {
    makeSound() {
        console.log("Some generic sound");
    }
}

class Dog extends Animal {
    makeSound() {
        console.log("Woof! Woof!");
    }
}

class Cat extends Animal {
    makeSound() {
        console.log("Meow!");
    }
}

// Polymorphism in action
function animalSound(animal) {
    animal.makeSound();  // Same call, different behavior
}

animalSound(new Dog());  // Woof! Woof!
animalSound(new Cat());  // Meow!
```javascript

**Key Point**: Same method (`makeSound`), different output based on object type.

## Types of Polymorphism

### 1. Compile-time Polymorphism (Static Polymorphism)

Resolved at compile time. The compiler determines which method to call based on method signatures.

**Method Overloading**: Same method name, different parameters
```javascript
Example concept:
class Calculator {
    add(int a, int b)           → returns int
    add(double a, double b)     → returns double
    add(int a, int b, int c)    → returns int
}
```

**Operator Overloading**: Same operator, different meanings
```javascript
Example:
+ operator: 
  - For numbers: 5 + 3 = 8
  - For strings: "Hello" + "World" = "HelloWorld"
```javascript

**When it happens**: At compile time (before program runs)

**How it works**: Compiler selects the correct method based on argument types and count

**Benefits**: Fast (no runtime overhead), type-safe

### 2. Runtime Polymorphism (Dynamic Polymorphism)

Resolved at runtime. The actual method called is determined by the object type during program execution.

**Method Overriding**: Child class provides specific implementation of parent method
```javascript
class Shape {
    area() {
        return 0;
    }
}

class Circle extends Shape {
    constructor(radius) {
        super();
        this.radius = radius;
    }
    
    area() {
        return Math.PI * this.radius ** 2;
    }
}

class Rectangle extends Shape {
    constructor(width, height) {
        super();
        this.width = width;
        this.height = height;
    }
    
    area() {
        return this.width * this.height;
    }
}

// Runtime polymorphism
const shapes = [
    new Circle(5),
    new Rectangle(4, 6)
];

shapes.forEach(shape => {
    console.log(`Area: ${shape.area()}`);  // Method determined at runtime
});
```text

**When it happens**: At runtime (while program runs)

**How it works**: Object's actual type determines which method executes

**Benefits**: Flexibility, extensibility, late binding

## Comparison: Compile-time vs Runtime
```
┌────────────────────────────────────────────────────┐
│        Compile-time vs Runtime Polymorphism         │
└────────────────────────────────────────────────────┘

Compile-time                Runtime
├─ Method overloading       ├─ Method overriding
├─ Operator overloading     ├─ Interface implementation
├─ Resolved at compile time ├─ Resolved at runtime
├─ Faster execution         ├─ More flexible
├─ Static binding           ├─ Dynamic binding
└─ Same class              └─ Parent-child relationship
```text

## Real-World Example: Payment Processing
```javascript
class PaymentMethod {
    pay(amount) {
        throw new Error("Must be implemented");
    }
}

class CreditCard extends PaymentMethod {
    pay(amount) {
        console.log(`Paid $${amount} with Credit Card`);
    }
}

class PayPal extends PaymentMethod {
    pay(amount) {
        console.log(`Paid $${amount} with PayPal`);
    }
}

// Checkout works with any payment method
class Checkout {
    processPayment(paymentMethod, amount) {
        paymentMethod.pay(amount);  // Polymorphic call
    }
}

const checkout = new Checkout();
checkout.processPayment(new CreditCard(), 100);
checkout.processPayment(new PayPal(), 50);
```text

## Benefits of Polymorphism
```
┌────────────────────────────────────────┐
│     Benefits of Polymorphism           │
└────────────────────────────────────────┘

Flexibility
└─ One interface, multiple implementations

Extensibility
└─ Add new types without changing existing code

Code Reuse
└─ Common interface for different objects

Maintainability
└─ Easier to manage and extend

Loose Coupling
└─ Code depends on abstractions
```text

## Key Takeaways

- **Two main types**: Compile-time (static) and Runtime (dynamic)
- **Compile-time**: Method/operator overloading, resolved before execution
- **Runtime**: Method overriding, resolved during execution
- **Same interface, many forms** of implementation
- **Enables flexible code** that works with multiple types
- **Makes systems** extensible and maintainable

## Summary of All Four Concepts
```
┌─────────────────────────────────────────────────────┐
│         OOP Fundamental Principles                   │
└─────────────────────────────────────────────────────┘

Encapsulation
└─ Bundle data and methods, hide internals

Abstraction
└─ Hide complexity, show only essentials

Inheritance
└─ Child class inherits from parent class
└─ Types: Single, Multilevel, Hierarchical, Multiple, Hybrid

Polymorphism
└─ Same interface, different implementations
└─ Types: Compile-time (overloading) and Runtime (overriding)
```text

These four pillars work together to create robust, maintainable, and flexible object-oriented systems.

---

# Class Relationships

In object-oriented design, classes don't exist in isolation—they interact and relate to each other in various ways. Understanding these relationships is crucial for creating well-structured, maintainable systems.

## Overview of Relationships
```text
┌────────────────────────────────────────────────────┐
│            Types of Class Relationships             │
└────────────────────────────────────────────────────┘

Association
└─ General "uses" relationship

Aggregation
└─ Weak "has-a" relationship (whole-part, part can exist independently)

Composition
└─ Strong "has-a" relationship (whole-part, part cannot exist independently)

Dependency
└─ "depends-on" relationship (temporary usage)

Realization
└─ "implements" relationship (interface implementation)
```javascript

### Relationship Strength (Weak → Strong)
```mermaid
flowchart LR
    Dependency --> Association --> Aggregation --> Composition
    Composition --> Realization
```

## Relationship Strength
```javascript
Weakest                                          Strongest
   │                                                  │
   ├─ Dependency                                     │
   ├─ Association                                    │
   ├─ Aggregation                                    │
   └─ Composition                                    │
                                                     │
                                            Realization
                                          (different type)
```javascript

---

# Association

Association represents a general relationship where one class uses or interacts with another class. It's the most basic form of relationship.

## What is Association?

**Association** is a "uses-a" or "has-a" relationship between two classes where both can exist independently.

**Core Idea**: Objects are aware of each other and interact, but neither owns the other

Think of **Doctor and Patient**:
- A doctor treats patients
- A patient consults doctors
- Both exist independently
- Neither owns the other

## Characteristics

**Independence**: Both objects can exist without each other

**Bidirectional or Unidirectional**: Can go one way or both ways

**Loose Coupling**: Objects are connected but not tightly bound

**Navigation**: Objects can reference each other

## Types of Association

### 1. Unidirectional Association

One class knows about the other, but not vice versa.
```
Teacher ────────> Student
(Teacher knows Student, Student doesn't know Teacher)
```text
```javascript
class Teacher {
    constructor(name) {
        this.name = name;
        this.students = [];
    }
    
    addStudent(student) {
        this.students.push(student);
    }
}

class Student {
    constructor(name) {
        this.name = name;
    }
}

const teacher = new Teacher("Mr. Smith");
const student = new Student("Alice");
teacher.addStudent(student);
```text

### 2. Bidirectional Association

Both classes know about each other.
```text
Teacher <────────> Student
(Both know each other)
```text
```
class Teacher {
    constructor(name) {
        this.name = name;
        this.students = [];
    }
    
    addStudent(student) {
        this.students.push(student);
        student.teacher = this;
    }
}

class Student {
    constructor(name) {
        this.name = name;
        this.teacher = null;
    }
}
```text

## Cardinality in Association
```text
One-to-One (1:1)
Person ──── Passport
(Each person has one passport)

One-to-Many (1:N)
Teacher ──── Students
(One teacher teaches many students)

Many-to-Many (M:N)
Students ──── Courses
(Students enroll in many courses, courses have many students)
```text

## Real-World Examples
```
Driver ────> Car
└─ Driver drives a car

Customer ────> Product
└─ Customer buys products

Author ────> Book
└─ Author writes books

Employee ────> Department
└─ Employee works in a department
```text

## Key Points

- **General relationship** between classes
- **Both objects exist independently**
- **Can be navigated** in one or both directions
- **Weakest form** of relationship (after dependency)

---

# Aggregation

Aggregation is a specialized form of association representing a "has-a" relationship where the part can exist independently of the whole.

## What is Aggregation?

**Aggregation** is a weak "has-a" relationship where the contained object can exist without the container.

**Core Idea**: Whole has parts, but parts can survive without the whole

Think of **Department and Professor**:
- A department has professors
- If the department closes, professors still exist
- Professors can move to other departments

## Visual Representation
```text
┌────────────┐           ┌───────────┐
│ Department │ ◇────────>│ Professor │
└────────────┘           └───────────┘
    (Whole)                 (Part)

Diamond symbol (◇) indicates aggregation
```sql

## Characteristics

**Weak Ownership**: Container has parts but doesn't own them

**Independent Lifecycle**: Parts can exist without the container

**Shared Parts**: Parts can belong to multiple containers

**Can be Empty**: Container can exist without parts

## Simple Example
```javascript
class Department {
    constructor(name) {
        this.name = name;
        this.professors = [];
    }
    
    addProfessor(professor) {
        this.professors.push(professor);
    }
    
    removeProfessor(professor) {
        const index = this.professors.indexOf(professor);
        if (index > -1) {
            this.professors.splice(index, 1);
        }
    }
}

class Professor {
    constructor(name) {
        this.name = name;
    }
}

// Professors exist independently
const prof1 = new Professor("Dr. Smith");
const prof2 = new Professor("Dr. Jones");

// Department has professors
const csDept = new Department("Computer Science");
csDept.addProfessor(prof1);
csDept.addProfessor(prof2);

// Department can be deleted, professors still exist
// delete csDept;  // prof1 and prof2 still exist
```

## Real-World Examples
```text
University ◇───> Students
└─ University has students, students exist independently

Library ◇───> Books
└─ Library contains books, books exist independently

Team ◇───> Players
└─ Team has players, players exist independently

Playlist ◇───> Songs
└─ Playlist contains songs, songs exist independently
```text

## Key Points

- **Weak "has-a"** relationship
- **Parts survive** when whole is destroyed
- **Parts can be shared** among multiple wholes
- **Represents collection** or grouping

---

# Composition

Composition is a strong "has-a" relationship where the part cannot exist without the whole. It represents ownership.

## What is Composition?

**Composition** is a strong "has-a" relationship where the contained object's lifecycle depends on the container.

**Core Idea**: Whole owns parts, parts die with the whole

Think of **House and Rooms**:
- A house has rooms
- If you demolish the house, rooms are destroyed
- Rooms cannot exist without the house

## Visual Representation
```text
┌───────┐           ┌──────┐
│ House │ ◆────────>│ Room │
└───────┘           └──────┘
 (Whole)             (Part)

Filled diamond (◆) indicates composition
```

## Characteristics

**Strong Ownership**: Container owns the parts

**Dependent Lifecycle**: Parts cannot exist without container

**Exclusive Parts**: Parts belong to only one container

**Created Together**: Parts are typically created with the container

## Simple Example
```javascript
class House {
    constructor(address) {
        this.address = address;
        // Rooms are created with the house (composition)
        this.rooms = [
            new Room("Living Room"),
            new Room("Bedroom"),
            new Room("Kitchen")
        ];
    }
}

class Room {
    constructor(name) {
        this.name = name;
    }
}

const myHouse = new House("123 Main St");
// When myHouse is destroyed, all rooms are destroyed too
```text

## Composition vs Aggregation
```
┌────────────────────────────────────────────────────┐
│        Aggregation vs Composition                   │
└────────────────────────────────────────────────────┘

Aggregation (◇)              Composition (◆)
├─ Weak relationship         ├─ Strong relationship
├─ Part can exist alone      ├─ Part dies with whole
├─ Shared ownership          ├─ Exclusive ownership
└─ Example: Library-Books    └─ Example: House-Rooms
```text

## Real-World Examples
```text
Car ◆───> Engine
└─ Car owns engine, engine dies with car

Book ◆───> Pages
└─ Book has pages, pages destroyed with book

Human ◆───> Heart
└─ Human has heart, heart cannot exist without human

Computer ◆───> CPU
└─ Computer has CPU, CPU part of computer
```text

## Code Example: Car and Engine
```
class Car {
    constructor(brand, model) {
        this.brand = brand;
        this.model = model;
        // Engine is part of car (composition)
        this.engine = new Engine("V8");
    }
    
    start() {
        this.engine.turnOn();
    }
}

class Engine {
    constructor(type) {
        this.type = type;
    }
    
    turnOn() {
        console.log(`${this.type} engine starting...`);
    }
}

const myCar = new Car("Ford", "Mustang");
// Engine is created with car and destroyed with car
```javascript

## Key Points

- **Strong "has-a"** relationship
- **Part cannot exist** without whole
- **Exclusive ownership** by container
- **Lifecycle dependent** on container
- **Stronger than aggregation**

---

# Dependency

Dependency is the weakest relationship where one class temporarily uses another class. The dependent class relies on the other class for a specific operation.

## What is Dependency?

**Dependency** exists when one class uses another class, typically as a method parameter, local variable, or return type.

**Core Idea**: One class depends on another for its functionality, but doesn't store a reference

Think of **Person using Phone**:
- Person makes a call using phone
- Person doesn't own the phone
- Phone is used temporarily and then released

## Visual Representation
```javascript
┌────────┐           ┌───────┐
│ Person │ - - - - ->│ Phone │
└────────┘           └───────┘
           (uses temporarily)

Dotted line indicates dependency
```javascript

## Characteristics

**Temporary Usage**: Class uses another only for specific operations

**No Ownership**: Dependent class doesn't store a reference

**Weakest Relationship**: Loosest form of coupling

**Method-Level**: Often appears in method parameters

## Simple Example
```javascript
class EmailService {
    sendEmail(message) {
        console.log(`Sending email: ${message}`);
    }
}

class User {
    constructor(name) {
        this.name = name;
    }
    
    // User depends on EmailService temporarily
    notifyUser(emailService, message) {
        emailService.sendEmail(message);
        // EmailService is used and discarded
    }
}

const user = new User("Alice");
const emailService = new EmailService();
user.notifyUser(emailService, "Welcome!");
```text

## Where Dependencies Occur

### 1. Method Parameter
```
class OrderProcessor {
    process(order, paymentGateway) {
        // Depends on paymentGateway temporarily
        paymentGateway.processPayment(order.amount);
    }
}
```text

### 2. Local Variable
```javascript
class ReportGenerator {
    generate() {
        // Creates dependency temporarily
        const formatter = new DateFormatter();
        const date = formatter.format(new Date());
        return `Report generated on ${date}`;
    }
}
```text

### 3. Return Type
```
class UserFactory {
    // Return type creates dependency
    createUser(name) {
        return new User(name);
    }
}
```text

## Real-World Examples
```text
Driver -----> GPS
└─ Driver uses GPS for navigation (doesn't own it)

Chef -----> Recipe
└─ Chef follows recipe temporarily

Student -----> Calculator
└─ Student uses calculator for exam

Developer -----> Library
└─ Developer uses library functions
```text

## Dependency vs Association
```
┌────────────────────────────────────────────────────┐
│        Dependency vs Association                    │
└────────────────────────────────────────────────────┘

Dependency                  Association
├─ Temporary usage         ├─ Long-term relationship
├─ No stored reference     ├─ Stored reference
├─ Method-level            ├─ Class-level
└─ Weakest coupling        └─ Stronger coupling
```javascript

## Key Points

- **Weakest relationship** type
- **Temporary usage** only
- **No permanent reference** stored
- **Method parameter** or local variable
- **Least coupling** between classes

---

# Realization

Realization is a relationship between an interface and a class that implements it. The class realizes (implements) the behavior defined by the interface.

## What is Realization?

**Realization** is the relationship where a class implements an interface, providing concrete implementations for abstract methods.

**Core Idea**: Interface defines contract, class fulfills the contract

Think of **Contract and Contractor**:
- Contract defines what must be done
- Contractor implements and delivers the work
- Multiple contractors can fulfill the same contract differently

## Visual Representation
```javascript
┌──────────────────┐
│   <<interface>>  │
│  PaymentGateway  │
└────────△─────────┘
         │
         │ realizes (implements)
         │
    ┌────┴─────┐
    │          │
    ▼          ▼
┌────────┐  ┌────────┐
│ Stripe │  │ PayPal │
└────────┘  └────────┘

Dotted line with hollow triangle indicates realization
```javascript

## Characteristics

**Contract Fulfillment**: Class must implement all interface methods

**Multiple Realizations**: Multiple classes can implement the same interface

**Polymorphism**: Enables using different implementations interchangeably

**Type Safety**: Ensures classes provide required behavior

## Simple Example
```javascript
// Interface (contract)
class Shape {
    area() {
        throw new Error("Must implement area()");
    }
    
    perimeter() {
        throw new Error("Must implement perimeter()");
    }
}

// Realization - Circle implements Shape
class Circle extends Shape {
    constructor(radius) {
        super();
        this.radius = radius;
    }
    
    area() {
        return Math.PI * this.radius ** 2;
    }
    
    perimeter() {
        return 2 * Math.PI * this.radius;
    }
}

// Realization - Rectangle implements Shape
class Rectangle extends Shape {
    constructor(width, height) {
        super();
        this.width = width;
        this.height = height;
    }
    
    area() {
        return this.width * this.height;
    }
    
    perimeter() {
        return 2 * (this.width + this.height);
    }
}

// Usage - polymorphic behavior
function printShapeInfo(shape) {
    console.log(`Area: ${shape.area()}`);
    console.log(`Perimeter: ${shape.perimeter()}`);
}

printShapeInfo(new Circle(5));
printShapeInfo(new Rectangle(4, 6));
```text

## Real-World Examples
```text
<<interface>> Drivable
     △
     │ realizes
     │
┌────┴─────┬──────┐
│          │      │
Car      Truck   Bus

<<interface>> Flyable
     △
     │ realizes
     │
┌────┴─────┬──────┐
│          │      │
Airplane  Bird   Drone

<<interface>> Drawable
     △
     │ realizes
     │
┌────┴─────┬──────┐
│          │      │
Circle  Square  Triangle
```text

## Benefits of Realization

**Flexibility**: Easy to add new implementations

**Polymorphism**: Use different implementations interchangeably

**Testability**: Mock interfaces for testing

**Loose Coupling**: Code depends on interfaces, not concrete classes

**Contract Enforcement**: Ensures required methods exist

## Key Points

- **Interface defines** what must be implemented
- **Class realizes** (implements) the interface
- **Multiple classes** can implement same interface
- **Enables polymorphism** and flexibility
- **Foundation of** contract-based programming

---

# Relationship Comparison

## Summary Table

| Relationship | Symbol | Strength | Lifecycle | Example |
|--------------|--------|----------|-----------|---------|
| **Dependency** | - - - -> | Weakest | Independent | Driver uses GPS |
| **Association** | ────> | Weak | Independent | Teacher teaches Student |
| **Aggregation** | ◇───> | Medium | Independent parts | Department has Professors |
| **Composition** | ◆───> | Strong | Dependent parts | House has Rooms |
| **Realization** | - - -△ | N/A | N/A | Class implements Interface |

## Visual Comparison
```text
┌────────────────────────────────────────────────────┐
│           Relationship Characteristics              │
└────────────────────────────────────────────────────┘

Dependency
└─ Uses temporarily, no permanent connection

Association
└─ Uses regularly, knows about each other

Aggregation (weak has-a)
└─ Contains parts that can exist independently

Composition (strong has-a)
└─ Contains parts that cannot exist independently

Realization
└─ Implements interface contract
```

## When to Use Each

**Use Dependency** when:
- One class occasionally uses another
- No need to store a reference
- Minimal coupling desired

**Use Association** when:
- Classes need to communicate regularly
- Both exist independently
- Long-term relationship

**Use Aggregation** when:
- Whole contains parts
- Parts can exist without whole
- Shared ownership possible

**Use Composition** when:
- Whole owns parts
- Parts cannot exist without whole
- Exclusive ownership required

**Use Realization** when:
- Defining contracts with interfaces
- Multiple implementations needed
- Polymorphic behavior desired

## Key Takeaways

All five relationships serve different purposes in object-oriented design:

- **Dependency** and **Association** connect classes at different coupling strengths
- **Aggregation** and **Composition** represent different levels of ownership
- **Realization** enables contract-based programming with interfaces

Understanding these relationships helps you design systems that are flexible, maintainable, and properly structured.

---

# Design Principles

Design principles are fundamental guidelines that help developers write better, more maintainable code. They serve as best practices that have proven effective across countless software projects.

## Why Design Principles Matter

**Quality Code**: Principles guide you toward clean, readable code

**Maintainability**: Well-designed code is easier to modify and extend

**Reduced Bugs**: Following principles helps prevent common mistakes

**Team Collaboration**: Shared principles create consistent codebases

**Long-term Success**: Good design pays off as systems grow

---

# DRY Principle

DRY stands for "Don't Repeat Yourself" - one of the most fundamental principles in software development.

## What is DRY?

**DRY Principle**: Every piece of knowledge should have a single, authoritative representation in the system.

**Core Idea**: Don't duplicate code or logic - write it once, reuse it everywhere

Think of a **recipe book**:
- If you change how to make pasta sauce, you update one recipe
- You don't want the same recipe written differently in multiple places
- One source of truth for each recipe

## Why DRY Matters

**Easier Maintenance**: Change logic in one place, not many

**Fewer Bugs**: No risk of updating one copy and forgetting others

**Consistency**: Same logic always behaves the same way

**Less Code**: Shorter, cleaner codebase

## Violation Example (WET - Write Everything Twice)
```javascript
// Bad - Repeated validation logic
function createUser(name, email) {
    if (!name || name.length < 3) {
        throw new Error("Invalid name");
    }
    if (!email || !email.includes('@')) {
        throw new Error("Invalid email");
    }
    // Create user
}

function updateUser(id, name, email) {
    if (!name || name.length < 3) {
        throw new Error("Invalid name");
    }
    if (!email || !email.includes('@')) {
        throw new Error("Invalid email");
    }
    // Update user
}

// Duplicated validation in both functions!
```javascript

## DRY Solution
```javascript
// Good - Single validation logic
function validateName(name) {
    if (!name || name.length < 3) {
        throw new Error("Invalid name");
    }
}

function validateEmail(email) {
    if (!email || !email.includes('@')) {
        throw new Error("Invalid email");
    }
}

function createUser(name, email) {
    validateName(name);
    validateEmail(email);
    // Create user
}

function updateUser(id, name, email) {
    validateName(name);
    validateEmail(email);
    // Update user
}
```javascript

## Common DRY Applications

**Functions**: Extract repeated code into reusable functions

**Constants**: Define values once, reference them everywhere

**Classes**: Create reusable components and utilities

**Configuration**: Centralize settings in one place

## When NOT to Apply DRY

**Coincidental Duplication**: Similar code that represents different concepts

**Premature Abstraction**: Don't abstract until you see the pattern clearly

**Over-Engineering**: Sometimes a little duplication is clearer than complex abstraction

## Key Takeaways

- **Write logic once**, reuse everywhere
- **Single source of truth** for each concept
- **Easier to maintain** and less error-prone
- **Balance** with readability and simplicity

---

# KISS Principle

KISS stands for "Keep It Simple, Stupid" - a principle that emphasizes simplicity in design and implementation.

## What is KISS?

**KISS Principle**: Systems work best when they're kept simple rather than made complex.

**Core Idea**: Choose the simplest solution that solves the problem

Think of **directions**:
- Simple: "Turn right at the gas station"
- Complex: "Proceed 0.3 miles northeast at 45 degrees, then execute a 90-degree clockwise rotation"
- Both work, but simple is better

## Why KISS Matters

**Easier to Understand**: Simple code is readable by everyone

**Fewer Bugs**: Less complexity means fewer places for bugs to hide

**Faster Development**: Simple solutions are quicker to implement

**Easier Maintenance**: Future developers can understand and modify it

**Better Performance**: Simple code often runs faster

## Violation Example
```javascript
// Bad - Overly complex
function isEven(number) {
    return number % 2 === 0 ? 
        (number === 0 ? 
            true : 
            (number > 0 ? 
                !isEven(number - 2) : 
                !isEven(number + 2)
            )
        ) : 
        false;
}
```javascript

## KISS Solution
```javascript
// Good - Simple and clear
function isEven(number) {
    return number % 2 === 0;
}
```javascript

## Real-World Example

**Problem**: Calculate discount price
```javascript
// Bad - Unnecessarily complex
function calculateDiscount(price, customerType) {
    const discountMatrix = {
        regular: { tier1: 0.05, tier2: 0.10 },
        premium: { tier1: 0.15, tier2: 0.20 },
        vip: { tier1: 0.25, tier2: 0.30 }
    };
    
    const tier = price > 1000 ? 'tier2' : 'tier1';
    const discount = discountMatrix[customerType][tier];
    
    return price - (price * discount);
}

// Good - Simple and clear
function calculateDiscount(price, discountPercent) {
    return price * (1 - discountPercent / 100);
}
```javascript

## Guidelines for KISS

**Use Clear Names**: Variable and function names should be obvious

**Avoid Clever Code**: Clever often means hard to understand

**Prefer Standard Solutions**: Use common patterns over custom ones

**Break Down Complexity**: Split complex functions into smaller ones

**Question Complexity**: If it feels complex, it probably is

## When Complexity is Justified

**Performance Requirements**: Sometimes optimization requires complexity

**Domain Complexity**: Some problems are inherently complex

**Security**: Security measures may add necessary complexity

## Key Takeaways

- **Simplicity over cleverness**
- **Clear and obvious** solutions are best
- **Less code** is often better code
- **Easy to understand** means easy to maintain

---

# YAGNI Principle

YAGNI stands for "You Aren't Gonna Need It" - a principle that warns against building functionality before it's actually needed.

## What is YAGNI?

**YAGNI Principle**: Don't implement something until you actually need it.

**Core Idea**: Build what you need now, not what you might need later

Think of **packing for a trip**:
- Don't pack "just in case" items for every scenario
- Pack what you know you'll need
- Buy the rest if needed

## Why YAGNI Matters

**Saves Time**: Don't waste effort on unused features

**Less Code**: Smaller codebase is easier to maintain

**Focused Development**: Work on what matters now

**Avoid Waste**: Unused code is wasted code

**Flexibility**: Easier to adapt when requirements change

## Violation Example
```javascript
// Bad - Building for hypothetical future needs
class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
        this.phone = null;           // Not needed yet
        this.address = null;          // Not needed yet
        this.preferences = {};        // Not needed yet
        this.socialMedia = [];        // Not needed yet
        this.paymentMethods = [];     // Not needed yet
        this.loginHistory = [];       // Not needed yet
        this.friends = [];            // Not needed yet
    }
    
    // Methods for features that don't exist yet
    addFriend(user) { /* ... */ }
    sendMessage(user, message) { /* ... */ }
    sharePost(post) { /* ... */ }
}

// Current requirement: Just store name and email!
```javascript

## YAGNI Solution
```javascript
// Good - Only what's needed now
class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }
}

// Add more fields when actually needed
```javascript

## Real-World Example
```javascript
// Bad - Overengineered for current needs
class EmailService {
    sendEmail(to, subject, body) { /* ... */ }
    sendBulkEmail(recipients) { /* ... */ }        // Not needed
    scheduleEmail(to, subject, body, time) { /* ... */ }  // Not needed
    sendEmailWithAttachment(to, subject, body, files) { /* ... */ }  // Not needed
    sendTemplatedEmail(to, templateId, data) { /* ... */ }  // Not needed
    trackEmailOpens(emailId) { /* ... */ }         // Not needed
    resendFailedEmails() { /* ... */ }             // Not needed
}

// Current need: Just send simple emails

// Good - Build what you need now
class EmailService {
    sendEmail(to, subject, body) {
        // Simple email sending
    }
}

// Add features when requirements demand them
```

## YAGNI in Practice

**Start Minimal**: Begin with the simplest implementation

**Iterate**: Add features when needed, not before

**Resist Speculation**: Don't code for "what if" scenarios

**Trust Refactoring**: You can always add functionality later

## Balancing YAGNI with Planning
```text
┌────────────────────────────────────────────────────┐
│           YAGNI vs Planning                         │
└────────────────────────────────────────────────────┘

YAGNI says:                  Good Planning says:
├─ Don't build it yet        ├─ Design for extensibility
├─ Wait for requirements     ├─ Consider future needs
├─ Avoid speculation         ├─ Architect wisely
└─ Build incrementally       └─ Avoid painting into corner

Balance: Design flexibly, implement minimally
```text

## When to Consider Future Needs

**Architecture**: Make high-level decisions that support growth

**Interfaces**: Design clean interfaces that allow extension

**Data Models**: Consider data structure carefully

**APIs**: Design public APIs thoughtfully (hard to change later)

## Key Takeaways

- **Build what you need now**, not what you might need
- **Avoid speculative features**
- **Trust that you can add** functionality later
- **Balance with good design** - be flexible but minimal

---

# Law of Demeter

The Law of Demeter (LoD), also called the "Principle of Least Knowledge," suggests that objects should only talk to their immediate neighbors, not reach through them to access distant objects.

## What is Law of Demeter?

**Law of Demeter**: An object should only interact with its immediate friends, not strangers.

**Core Idea**: Don't reach through objects to access their internals

Think of **asking a friend for money**:
- Don't: Reach into your friend's pocket and take their wallet
- Do: Ask your friend, who gets their own wallet

## The Rule

An object's method should only call methods on:
```javascript
1. The object itself (this)
2. Objects passed as parameters
3. Objects it creates
4. Its direct properties/fields
```javascript

**Should NOT** call methods on objects returned by other methods (method chaining through multiple objects).

## Violation Example
```javascript
// Bad - Violates Law of Demeter
class Wallet {
    constructor(money) {
        this.money = money;
    }
    
    getMoney() {
        return this.money;
    }
}

class Person {
    constructor(wallet) {
        this.wallet = wallet;
    }
    
    getWallet() {
        return this.wallet;
    }
}

// Customer reaches through Person to get Wallet to get Money
class ShoppingCart {
    checkout(person, amount) {
        // Too many dots! person.getWallet().getMoney()
        if (person.getWallet().getMoney() >= amount) {
            return true;
        }
        return false;
    }
}
```javascript

**Problem**: ShoppingCart knows too much about Person's internals (that Person has a Wallet, and Wallet has Money)

## Following Law of Demeter
```javascript
// Good - Respects Law of Demeter
class Wallet {
    constructor(money) {
        this.money = money;
    }
    
    hasEnoughMoney(amount) {
        return this.money >= amount;
    }
}

class Person {
    constructor(wallet) {
        this.wallet = wallet;
    }
    
    canAfford(amount) {
        return this.wallet.hasEnoughMoney(amount);
    }
}

// Clean - Only talks to its immediate friend (Person)
class ShoppingCart {
    checkout(person, amount) {
        if (person.canAfford(amount)) {
            return true;
        }
        return false;
    }
}
```

**Benefit**: ShoppingCart only knows about Person, not about Wallet or Money

## Real-World Example
```javascript
// Bad - Reaching through objects
class Order {
    process(customer) {
        const street = customer.getAddress().getStreet().getName();
        const city = customer.getAddress().getCity().getName();
        // Too much knowledge about customer's structure
    }
}

// Good - Ask, don't reach
class Order {
    process(customer) {
        const shippingAddress = customer.getShippingAddress();
        // Customer handles its own complexity
    }
}

class Customer {
    getShippingAddress() {
        // Customer knows how to get its own address
        return `${this.address.street.name}, ${this.address.city.name}`;
    }
}
```javascript

## Benefits of Law of Demeter

**Loose Coupling**: Objects are less dependent on each other's structure

**Easier Changes**: Modify internal structure without breaking external code

**Better Encapsulation**: Objects keep their internals hidden

**Reduced Ripple Effects**: Changes in one class don't cascade through many

## Visual Understanding
```text
Violation:
A → B.getC() → C.getD() → D.getValue()
(A knows about B, C, and D's structure)

Following LoD:
A → B.getValue()
(A only knows about B, B handles the rest)
```javascript

## When to Break the Rule

**Fluent APIs**: Builder patterns intentionally chain methods
```javascript
// Acceptable chaining
query
    .select('*')
    .from('users')
    .where('age > 18')
    .execute();
```sql

**Data Structures**: Simple data holders without behavior
```javascript
// Acceptable for plain objects
const name = user.profile.name;
```javascript

## Key Takeaways

- **Talk to friends**, not strangers
- **One dot is fine**, multiple dots are suspicious
- **Objects should ask**, not dig
- **Reduces coupling** and improves encapsulation

---

# Separation of Concerns

Separation of Concerns (SoC) is a design principle for separating a system into distinct sections, each handling a specific concern or responsibility.

## What is Separation of Concerns?

**Separation of Concerns**: Different parts of the system should handle different responsibilities.

**Core Idea**: Each module, class, or function should focus on one specific concern

Think of a **restaurant**:
- Chef cooks (doesn't handle payments)
- Waiter serves (doesn't cook)
- Cashier handles payments (doesn't cook or serve)
- Each role has clear, separate responsibilities

## Why SoC Matters

**Easier Understanding**: Each part has a clear purpose

**Simpler Maintenance**: Changes to one concern don't affect others

**Better Reusability**: Separated concerns can be reused

**Parallel Development**: Teams can work on different concerns simultaneously

**Easier Testing**: Test each concern independently

## Violation Example
```javascript
// Bad - Mixed concerns
class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }
    
    saveToDatabase() {
        // Business logic mixed with data access
        const connection = getDbConnection();
        connection.query(
            `INSERT INTO users (name, email) VALUES (?, ?)`,
            [this.name, this.email]
        );
    }
    
    sendWelcomeEmail() {
        // Business logic mixed with email sending
        const emailClient = getEmailClient();
        emailClient.send(
            this.email,
            "Welcome!",
            `Hello ${this.name}, welcome to our platform!`
        );
    }
    
    renderHTML() {
        // Business logic mixed with presentation
        return `<div><h1>${this.name}</h1><p>${this.email}</p></div>`;
    }
}
```javascript

**Problem**: User class handles business logic, database, email, and UI

## Separation of Concerns Solution
```javascript
// Good - Separated concerns

// 1. Business Logic (Domain Model)
class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }
    
    validate() {
        return this.name && this.email;
    }
}

// 2. Data Access (Repository)
class UserRepository {
    save(user) {
        const connection = getDbConnection();
        connection.query(
            `INSERT INTO users (name, email) VALUES (?, ?)`,
            [user.name, user.email]
        );
    }
}

// 3. Email Service (Notification)
class EmailService {
    sendWelcomeEmail(user) {
        const emailClient = getEmailClient();
        emailClient.send(
            user.email,
            "Welcome!",
            `Hello ${user.name}, welcome!`
        );
    }
}

// 4. Presentation (View)
class UserView {
    renderHTML(user) {
        return `<div><h1>${user.name}</h1><p>${user.email}</p></div>`;
    }
}
```

## Common Concern Separations
```javascript
┌────────────────────────────────────────────────────┐
│           Typical Concern Layers                    │
└────────────────────────────────────────────────────┘

Presentation Layer
├─ UI components
├─ User interaction
└─ Display formatting

Business Logic Layer
├─ Domain rules
├─ Validation
└─ Business workflows

Data Access Layer
├─ Database queries
├─ Data persistence
└─ External APIs

Infrastructure Layer
├─ Logging
├─ Configuration
└─ External services
```javascript

## Real-World Example: E-commerce
```javascript
// Separated concerns in order processing

// Domain Model
class Order {
    constructor(items, customer) {
        this.items = items;
        this.customer = customer;
    }
    
    calculateTotal() {
        return this.items.reduce((sum, item) => sum + item.price, 0);
    }
}

// Data Access
class OrderRepository {
    save(order) {
        // Database logic only
    }
}

// Business Service
class OrderService {
    placeOrder(order) {
        // Business logic only
        if (order.calculateTotal() > 0) {
            return true;
        }
        return false;
    }
}

// Email Service
class NotificationService {
    sendOrderConfirmation(order) {
        // Email logic only
    }
}

// Payment Service
class PaymentService {
    processPayment(order) {
        // Payment logic only
    }
}
```javascript

## Benefits Visualized
```text
Without SoC:
┌─────────────────────────┐
│    Giant Class          │
│  - Business logic       │
│  - Database access      │
│  - UI rendering         │
│  - Email sending        │
│  - Payment processing   │
└─────────────────────────┘
Hard to maintain, test, understand

With SoC:
┌──────────┐ ┌──────────┐ ┌──────────┐
│Business  │ │ Database │ │   UI     │
│  Logic   │ │  Access  │ │ Render   │
└──────────┘ └──────────┘ └──────────┘
┌──────────┐ ┌──────────┐
│  Email   │ │ Payment  │
│ Service  │ │ Service  │
└──────────┘ └──────────┘
Easy to maintain, test, understand
```javascript

## Key Takeaways

- **Each module** handles one specific concern
- **Different responsibilities** in different places
- **Easier to maintain** and understand
- **Better organization** and structure

---

# Coupling and Cohesion

Coupling and Cohesion are two fundamental concepts that measure the quality of code organization. They work together to define how well-structured your system is.

## What are Coupling and Cohesion?

**Coupling**: The degree of interdependence between modules

**Cohesion**: The degree to which elements within a module belong together

**Goal**: Low coupling, high cohesion

Think of **LEGO blocks**:
- Low coupling: Blocks connect easily but separate easily
- High cohesion: Pieces of a specific model fit together perfectly for one purpose

## Coupling

### What is Coupling?

**Coupling** measures how much one class depends on another.
```
High Coupling (Bad)
└─ Classes tightly dependent on each other

Low Coupling (Good)
└─ Classes independent, loosely connected
```text

### Types of Coupling
```javascript
Tight Coupling (High) - Bad
├─ Classes know internal details of other classes
├─ Changes in one break others
└─ Hard to test and reuse

Loose Coupling (Low) - Good
├─ Classes interact through interfaces
├─ Changes don't ripple through system
└─ Easy to test and reuse
```javascript

### Tight Coupling Example
```javascript
// Bad - Tight coupling
class OrderProcessor {
    processOrder(order) {
        // Directly creates and uses specific payment class
        const payment = new StripePayment();
        payment.setApiKey("sk_test_123");
        payment.charge(order.amount);
        
        // Tightly coupled to Stripe implementation
        // Hard to switch to PayPal or another provider
    }
}
```javascript

### Loose Coupling Example
```javascript
// Good - Loose coupling
class OrderProcessor {
    constructor(paymentService) {
        this.paymentService = paymentService;
    }
    
    processOrder(order) {
        // Uses interface, doesn't care about implementation
        this.paymentService.charge(order.amount);
    }
}

// Easy to swap implementations
const processor1 = new OrderProcessor(new StripePayment());
const processor2 = new OrderProcessor(new PayPalPayment());
```

## Cohesion

### What is Cohesion?

**Cohesion** measures how closely related the responsibilities within a module are.
```text
High Cohesion (Good)
└─ Module does one thing well

Low Cohesion (Bad)
└─ Module does many unrelated things
```text

### Types of Cohesion
```text
Low Cohesion (Bad)
├─ Unrelated functionalities together
├─ Hard to understand purpose
└─ Changes affect many things

High Cohesion (Good)
├─ Related functionalities together
├─ Clear single purpose
└─ Changes are localized
```

### Low Cohesion Example
```javascript
// Bad - Low cohesion
class UserManager {
    createUser(name, email) { /* ... */ }
    
    sendEmail(to, subject, body) { /* ... */ }
    
    calculateTax(amount) { /* ... */ }
    
    generateReport() { /* ... */ }
    
    connectToDatabase() { /* ... */ }
}

// Unrelated responsibilities mixed together
```javascript

### High Cohesion Example
```javascript
// Good - High cohesion
class UserService {
    createUser(name, email) { /* ... */ }
    updateUser(id, data) { /* ... */ }
    deleteUser(id) { /* ... */ }
    findUser(id) { /* ... */ }
}

// All methods relate to user management

class EmailService {
    send(to, subject, body) { /* ... */ }
    sendBulk(recipients, subject, body) { /* ... */ }
}

// All methods relate to email

class TaxCalculator {
    calculate(amount) { /* ... */ }
    applyDeductions(amount) { /* ... */ }
}

// All methods relate to tax calculation
```text

## Coupling vs Cohesion
```text
┌────────────────────────────────────────────────────┐
│         Ideal Software Design                       │
└────────────────────────────────────────────────────┘

              High Cohesion
                    ↑
                    │
                    │
    ┌───────────────┼───────────────┐
    │               │               │
    │   IDEAL       │               │
    │   ZONE        │               │
    │               │               │
    ├───────────────┼───────────────┤
    │               │               │
    │               │               │
    └───────────────┼───────────────┘
                    │
                    │
Low Coupling ←──────┼──────→ High Coupling
                    │
                    ↓
              Low Cohesion
```javascript

## Real-World Comparison

### Poor Design (High Coupling, Low Cohesion)
```javascript
// Bad - Everything mixed together
class Application {
    // Database access
    saveToDb(data) { /* ... */ }
    
    // UI rendering
    renderPage() { /* ... */ }
    
    // Business logic
    processOrder() { /* ... */ }
    
    // Email
    sendEmail() { /* ... */ }
    
    // Payment
    chargeCard() { /* ... */ }
}

// High coupling: Everything depends on everything
// Low cohesion: Unrelated responsibilities together
```javascript

### Good Design (Low Coupling, High Cohesion)
```javascript
// Good - Well organized

// High cohesion - only order-related logic
class OrderService {
    createOrder(order) { /* ... */ }
    cancelOrder(id) { /* ... */ }
    validateOrder(order) { /* ... */ }
}

// High cohesion - only database operations
class OrderRepository {
    save(order) { /* ... */ }
    findById(id) { /* ... */ }
    delete(id) { /* ... */ }
}

// High cohesion - only email operations
class EmailService {
    sendOrderConfirmation(order) { /* ... */ }
}

// Low coupling - classes interact through interfaces
class OrderController {
    constructor(orderService, emailService) {
        this.orderService = orderService;
        this.emailService = emailService;
    }
}
```text

## Benefits of Low Coupling + High Cohesion

**Maintainability**: Changes are isolated and predictable

**Testability**: Easy to test each module independently

**Reusability**: Cohesive modules can be reused elsewhere

**Understandability**: Clear purpose for each module

**Flexibility**: Easy to modify and extend

## Key Takeaways

**Coupling**:
- Measure of interdependence between modules
- Aim for **low coupling** (loose connections)
- Use interfaces and dependency injection

**Cohesion**:
- Measure of how related responsibilities are
- Aim for **high cohesion** (focused purpose)
- Single Responsibility Principle

**Together**: Low coupling + High cohesion = Good design

---

# Composing Objects Principle

The Composing Objects Principle, often summarized as "Favor Composition Over Inheritance," suggests building complex functionality by combining simple objects rather than creating deep inheritance hierarchies.

## What is Composition?

**Composition**: Building complex objects by combining simpler objects.

**Core Idea**: "Has-a" relationships are often better than "is-a" relationships

Think of a **smartphone**:
- Not built as one giant component
- Composed of: camera, battery, screen, processor
- Each part can be upgraded independently

## Composition vs Inheritance
```text
┌────────────────────────────────────────────────────┐
│       Composition vs Inheritance                    │
└────────────────────────────────────────────────────┘

Inheritance (Is-a)          Composition (Has-a)
├─ Rigid hierarchy          ├─ Flexible structure
├─ Compile-time binding     ├─ Runtime flexibility
├─ Tight coupling           ├─ Loose coupling
├─ Hard to change           ├─ Easy to change
└─ "Car is a Vehicle"       └─ "Car has an Engine"
```

## Problem with Deep Inheritance
```javascript
// Bad - Deep inheritance hierarchy
class Vehicle {
    start() { /* ... */ }
    stop() { /* ... */ }
}

class LandVehicle extends Vehicle {
    drive() { /* ... */ }
}

class WaterVehicle extends Vehicle {
    sail() { /* ... */ }
}

class AmphibiousVehicle extends LandVehicle {
    // Problem: How to add sailing?
    // Can't inherit from both LandVehicle and WaterVehicle
}

// Inheritance creates rigid hierarchies
```javascript

## Solution with Composition
```javascript
// Good - Using composition
class Engine {
    start() {
        console.log("Engine starting");
    }
    stop() {
        console.log("Engine stopping");
    }
}

class Wheels {
    drive() {
        console.log("Driving on land");
    }
}

class Propeller {
    sail() {
        console.log("Sailing on water");
    }
}

// Compose vehicle from parts
class AmphibiousVehicle {
    constructor() {
        this.engine = new Engine();
        this.wheels = new Wheels();
        this.propeller = new Propeller();
    }
    
    startEngine() {
        this.engine.start();
    }
    
    driveOnLand() {
        this.wheels.drive();
    }
    
    sailOnWater() {
        this.propeller.sail();
    }
}

const vehicle = new AmphibiousVehicle();
vehicle.startEngine();
vehicle.driveOnLand();
vehicle.sailOnWater();
```javascript

## Real-World Example: Game Characters

### With Inheritance (Problematic)
```javascript
// Bad - Inheritance explosion
class Character { }
class FlyingCharacter extends Character { }
class ShootingCharacter extends Character { }
class FlyingShootingCharacter extends FlyingCharacter { }
// What about SwimmingShootingFlyingCharacter?
// Hierarchy becomes unmaintainable
```javascript

### With Composition (Flexible)
```javascript
// Good - Composition approach
class FlyBehavior {
    fly() {
        console.log("Flying");
    }
}

class ShootBehavior {
    shoot() {
        console.log("Shooting");
    }
}

class SwimBehavior {
    swim() {
        console.log("Swimming");
    }
}

class Character {
    constructor(behaviors) {
        this.behaviors = behaviors;
    }
    
    performActions() {
        this.behaviors.forEach(behavior => {
            Object.keys(behavior).forEach(action => {
                behavior[action]();
            });
        });
    }
}

// Create any combination
const hero = new Character([
    new FlyBehavior(),
    new ShootBehavior(),
    new SwimBehavior()
]);

hero.performActions();
// Flying
// Shooting
// Swimming
```sql

## Benefits of Composition

**Flexibility**: Change behavior at runtime

**Reusability**: Compose existing components in new ways

**Loose Coupling**: Components are independent

**Easy Testing**: Test each component separately

**Avoid Hierarchy Problems**: No deep inheritance trees

## When to Use Each

### Use Inheritance When:
- Clear "is-a" relationship exists
- Shared behavior across subclasses
- Hierarchy is shallow and stable

### Use Composition When:
- Need runtime flexibility
- Want to avoid rigid hierarchies
- Combining behaviors from multiple sources
- Behavior changes frequently

### Inheritance vs Composition (Decision Guide)
```mermaid
flowchart TD
    A[Need reuse?] --> B{Is-a relationship?}
    B -- Yes --> C{Stable hierarchy?}
    C -- Yes --> D[Use Inheritance]
    C -- No --> E[Use Composition]
    B -- No --> E[Use Composition]
```

## Practical Example: Logger
```javascript
// Using composition for flexible logging
class ConsoleLogger {
    log(message) {
        console.log(message);
    }
}

class FileLogger {
    log(message) {
        // Write to file
    }
}

class TimestampDecorator {
    constructor(logger) {
        this.logger = logger;
    }
    
    log(message) {
        const timestamp = new Date().toISOString();
        this.logger.log(`[${timestamp}] ${message}`);
    }
}

// Compose behaviors
const logger = new TimestampDecorator(
    new ConsoleLogger()
);

logger.log("Application started");
// [2024-01-15T10:30:00.000Z] Application started
```text

## Key Takeaways

- **Favor composition** over deep inheritance
- **"Has-a" often better** than "is-a"
- **More flexible**

---


# SOLID Principles

SOLID is an acronym for five design principles that help create more maintainable, flexible, and scalable object-oriented software. These principles were introduced by Robert C. Martin (Uncle Bob) and have become fundamental guidelines in software development.

## What is SOLID?

```text
S — Single Responsibility Principle
O — Open/Closed Principle
L — Liskov Substitution Principle
I — Interface Segregation Principle
D — Dependency Inversion Principle
```

## Why SOLID Matters

**Better Design**: Creates well-structured, organized code

**Easier Maintenance**: Changes are localized and predictable

**Flexibility**: Systems adapt to new requirements easily

**Testability**: Code is easier to test in isolation

**Reduced Bugs**: Clear responsibilities reduce errors

**Team Collaboration**: Common principles improve communication

### SOLID Quick Check (Flowchart)
```mermaid
flowchart TD
    A[Change Request] --> B{One reason to change?}
    B -- No --> SRP[Apply SRP]
    B -- Yes --> C{Need new behavior?}
    C -- Yes --> OCP[Prefer extension]
    C -- No --> D{Subclass still valid?}
    D -- No --> LSP[Fix contract]
    D -- Yes --> E{Interface too broad?}
    E -- Yes --> ISP[Split interfaces]
    E -- No --> F{High-level depends on low-level?}
    F -- Yes --> DIP[Depend on abstractions]
```

---

# Single Responsibility Principle (SRP)

The Single Responsibility Principle states that a class should have only one reason to change, meaning it should have only one job or responsibility.

## What is SRP?

**Single Responsibility Principle**: A class should have one, and only one, reason to change.

**Core Idea**: Each class does one thing and does it well

Think of a **restaurant**:
- Chef only cooks
- Waiter only serves
- Cashier only handles payments
- Each person has one clear responsibility

## Why SRP Matters

**Easier to Understand**: Clear purpose for each class

**Easier to Maintain**: Changes affect only one responsibility

**Easier to Test**: Test one responsibility at a time

**Reduced Coupling**: Classes don't depend on multiple concerns

**Better Organization**: System structure is logical

## Violation Example

```javascript
// Bad - Multiple responsibilities in one class
class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }
    
    // Responsibility 1: User data management
    getUserInfo() {
        return `${this.name} (${this.email})`;
    }
    
    // Responsibility 2: Database operations
    saveToDatabase() {
        const db = connectToDatabase();
        db.execute(`INSERT INTO users VALUES (?, ?)`, [this.name, this.email]);
    }
    
    // Responsibility 3: Email operations
    sendWelcomeEmail() {
        const emailService = getEmailService();
        emailService.send(this.email, "Welcome!", "Thanks for joining!");
    }
    
    // Responsibility 4: Validation
    validateEmail() {
        return this.email.includes('@');
    }
    
    // Responsibility 5: Logging
    logActivity(action) {
        console.log(`User ${this.name} performed: ${action}`);
    }
}

// Too many reasons to change:
// - Database schema changes
// - Email service changes
// - Validation rules change
// - Logging format changes
```

**Problems**:
- User class has 5 different responsibilities
- Changes to database affect User class
- Changes to email affect User class
- Hard to test individual responsibilities

## SRP Solution

```javascript
// Good - Single responsibility per class

// Responsibility 1: User data (Domain Model)
class User {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }
    
    getUserInfo() {
        return `${this.name} (${this.email})`;
    }
}

// Responsibility 2: Database operations
class UserRepository {
    save(user) {
        const db = connectToDatabase();
        db.execute(`INSERT INTO users VALUES (?, ?)`, [user.name, user.email]);
    }
    
    findById(id) {
        // Find user logic
    }
}

// Responsibility 3: Email operations
class EmailService {
    sendWelcomeEmail(user) {
        const emailService = getEmailService();
        emailService.send(user.email, "Welcome!", "Thanks for joining!");
    }
}

// Responsibility 4: Validation
class UserValidator {
    validateEmail(email) {
        return email.includes('@');
    }
    
    validateName(name) {
        return name.length > 0;
    }
}

// Responsibility 5: Logging
class ActivityLogger {
    logUserActivity(user, action) {
        console.log(`User ${user.name} performed: ${action}`);
    }
}
```javascript

**Benefits**:
- Each class has one clear purpose
- Changes are isolated
- Easy to test each responsibility
- Easy to reuse components

## Real-World Example: Order Processing

```javascript
// Bad - Multiple responsibilities
class Order {
    constructor(items, customer) {
        this.items = items;
        this.customer = customer;
    }
    
    calculateTotal() { /* ... */ }
    saveToDatabase() { /* ... */ }
    sendConfirmationEmail() { /* ... */ }
    generateInvoicePDF() { /* ... */ }
    processPayment() { /* ... */ }
}

// Good - Single responsibility
class Order {
    constructor(items, customer) {
        this.items = items;
        this.customer = customer;
    }
    
    calculateTotal() {
        return this.items.reduce((sum, item) => sum + item.price, 0);
    }
}

class OrderRepository {
    save(order) { /* Database logic */ }
}

class OrderEmailService {
    sendConfirmation(order) { /* Email logic */ }
}

class InvoiceGenerator {
    generate(order) { /* PDF generation logic */ }
}

class PaymentProcessor {
    process(order) { /* Payment logic */ }
}
```javascript

## How to Identify SRP Violations

Ask these questions:
- **Does this class do more than one thing?**
- **How many reasons could cause this class to change?**
- **Can I describe the class purpose in one sentence without using "and"?**

If answers suggest multiple responsibilities, refactor.

## Key Takeaways

- **One class, one responsibility**
- **One reason to change**
- **Makes code easier** to understand, maintain, and test
- **Think**: "Does this class do one thing well?"

---

# Open/Closed Principle (OCP)

The Open/Closed Principle states that software entities should be open for extension but closed for modification.

## What is OCP?

**Open/Closed Principle**: Classes should be open for extension but closed for modification.

**Core Idea**: Add new functionality without changing existing code

Think of a **smartphone**:
- You can extend functionality by installing apps (open for extension)
- You don't modify the phone's operating system (closed for modification)

## Why OCP Matters

**Stability**: Existing code remains stable and tested

**Flexibility**: Easy to add new features

**Reduced Risk**: Changes don't break existing functionality

**Maintainability**: Less code churn

## Violation Example

```javascript
// Bad - Violates OCP
class PaymentProcessor {
    processPayment(amount, type) {
        if (type === 'creditcard') {
            console.log(`Processing credit card payment: $${amount}`);
            // Credit card logic
        } else if (type === 'paypal') {
            console.log(`Processing PayPal payment: $${amount}`);
            // PayPal logic
        } else if (type === 'bitcoin') {
            console.log(`Processing Bitcoin payment: $${amount}`);
            // Bitcoin logic
        }
        // Adding new payment method requires modifying this class
    }
}

// Problem: Every new payment method requires changing this class
```javascript

**Problems**:
- Must modify `PaymentProcessor` for each new payment type
- Risk of breaking existing payment methods
- Violates OCP (not closed for modification)

## OCP Solution

```javascript
// Good - Follows OCP

// Base class/interface
class PaymentMethod {
    processPayment(amount) {
        throw new Error("Must implement processPayment()");
    }
}

// Extensions - each payment method is a separate class
class CreditCardPayment extends PaymentMethod {
    processPayment(amount) {
        console.log(`Processing credit card payment: $${amount}`);
        // Credit card specific logic
    }
}

class PayPalPayment extends PaymentMethod {
    processPayment(amount) {
        console.log(`Processing PayPal payment: $${amount}`);
        // PayPal specific logic
    }
}

class BitcoinPayment extends PaymentMethod {
    processPayment(amount) {
        console.log(`Processing Bitcoin payment: $${amount}`);
        // Bitcoin specific logic
    }
}

// Payment processor doesn't need to change
class PaymentProcessor {
    constructor(paymentMethod) {
        this.paymentMethod = paymentMethod;
    }
    
    process(amount) {
        this.paymentMethod.processPayment(amount);
    }
}

// Usage - easy to extend with new payment methods
const processor1 = new PaymentProcessor(new CreditCardPayment());
processor1.process(100);

const processor2 = new PaymentProcessor(new PayPalPayment());
processor2.process(50);

// Add new payment method without modifying existing code
class CryptoPayment extends PaymentMethod {
    processPayment(amount) {
        console.log(`Processing crypto payment: $${amount}`);
    }
}

const processor3 = new PaymentProcessor(new CryptoPayment());
processor3.process(75);
```javascript

**Benefits**:
- Add new payment methods without changing `PaymentProcessor`
- Existing code remains untouched and stable
- Easy to test new payment methods independently

## Real-World Example: Discount Calculator

```javascript
// Bad - Violates OCP
class DiscountCalculator {
    calculate(customer, amount) {
        if (customer.type === 'regular') {
            return amount * 0.05;
        } else if (customer.type === 'premium') {
            return amount * 0.10;
        } else if (customer.type === 'vip') {
            return amount * 0.20;
        }
        // Must modify for new customer types
    }
}

// Good - Follows OCP
class DiscountStrategy {
    calculate(amount) {
        throw new Error("Must implement calculate()");
    }
}

class RegularDiscount extends DiscountStrategy {
    calculate(amount) {
        return amount * 0.05;
    }
}

class PremiumDiscount extends DiscountStrategy {
    calculate(amount) {
        return amount * 0.10;
    }
}

class VIPDiscount extends DiscountStrategy {
    calculate(amount) {
        return amount * 0.20;
    }
}

class DiscountCalculator {
    constructor(strategy) {
        this.strategy = strategy;
    }
    
    calculate(amount) {
        return this.strategy.calculate(amount);
    }
}

// Easy to add new discount types
class GoldDiscount extends DiscountStrategy {
    calculate(amount) {
        return amount * 0.15;
    }
}
```javascript

## Achieving OCP

**Use Abstraction**: Depend on interfaces/abstract classes

**Use Polymorphism**: Different implementations of same interface

**Use Design Patterns**: Strategy, Template Method, Decorator patterns

**Encapsulate Variation**: Isolate parts that change

## Key Takeaways

- **Open for extension**: Add new functionality easily
- **Closed for modification**: Don't change existing code
- **Use inheritance/interfaces** to achieve OCP
- **Benefits**: Stable, flexible, maintainable code

---

# Liskov Substitution Principle (LSP)

The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of a subclass without breaking the application.

## What is LSP?

**Liskov Substitution Principle**: Subtypes must be substitutable for their base types.

**Core Idea**: Child classes should be able to replace parent classes without causing issues

Think of **electric vehicles and gas vehicles**:
- Both are vehicles
- You can drive either one
- If code works with Vehicle, it should work with ElectricVehicle or GasVehicle

## Why LSP Matters

**Predictability**: Child classes behave as expected

**Reliability**: Substitution doesn't break functionality

**Polymorphism**: Use base class reference with confidence

**Maintainability**: Changes to hierarchy don't surprise users

## Violation Example

```javascript
// Bad - Violates LSP
class Bird {
    fly() {
        console.log("Flying");
    }
}

class Sparrow extends Bird {
    fly() {
        console.log("Sparrow flying");
    }
}

class Penguin extends Bird {
    fly() {
        throw new Error("Penguins can't fly!");
    }
}

// Usage
function makeBirdFly(bird) {
    bird.fly();  // Works for Sparrow, breaks for Penguin
}

makeBirdFly(new Sparrow());  // OK
makeBirdFly(new Penguin());  // Error! Violates LSP
```javascript

**Problem**: Penguin can't be substituted for Bird because it breaks the `fly()` contract

## LSP Solution

```javascript
// Good - Follows LSP

// Base class without fly method
class Bird {
    eat() {
        console.log("Bird eating");
    }
}

// Separate interface for flying birds
class FlyingBird extends Bird {
    fly() {
        console.log("Flying");
    }
}

class Sparrow extends FlyingBird {
    fly() {
        console.log("Sparrow flying");
    }
}

class Penguin extends Bird {
    swim() {
        console.log("Penguin swimming");
    }
}

// Usage
function makeFlyingBirdFly(bird) {
    bird.fly();  // Only accepts FlyingBird
}

makeFlyingBirdFly(new Sparrow());  // OK
// makeFlyingBirdFly(new Penguin());  // Won't compile/runtime error prevented
```javascript

**Benefits**:
- Clear separation: Flying vs non-flying birds
- Penguin doesn't promise to fly
- Substitution works correctly

## Real-World Example: Rectangle and Square

```javascript
// Bad - Classic LSP violation
class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }
    
    setWidth(width) {
        this.width = width;
    }
    
    setHeight(height) {
        this.height = height;
    }
    
    getArea() {
        return this.width * this.height;
    }
}

class Square extends Rectangle {
    setWidth(width) {
        this.width = width;
        this.height = width;  // Square must maintain equal sides
    }
    
    setHeight(height) {
        this.width = height;  // Square must maintain equal sides
        this.height = height;
    }
}

// Usage - breaks expectations
function resizeRectangle(rectangle) {
    rectangle.setWidth(5);
    rectangle.setHeight(4);
    
    const area = rectangle.getArea();
    console.log(`Expected area: 20, Got: ${area}`);
}

resizeRectangle(new Rectangle(0, 0));  // Area: 20 ✓
resizeRectangle(new Square(0));        // Area: 16 ✗ (violates LSP)
```

**Problem**: Square changes behavior - setting width also changes height

## LSP Solution for Rectangle/Square

```javascript
// Good - Follows LSP
class Shape {
    getArea() {
        throw new Error("Must implement getArea()");
    }
}

class Rectangle extends Shape {
    constructor(width, height) {
        super();
        this.width = width;
        this.height = height;
    }
    
    setWidth(width) {
        this.width = width;
    }
    
    setHeight(height) {
        this.height = height;
    }
    
    getArea() {
        return this.width * this.height;
    }
}

class Square extends Shape {
    constructor(side) {
        super();
        this.side = side;
    }
    
    setSide(side) {
        this.side = side;
    }
    
    getArea() {
        return this.side * this.side;
    }
}

// Both can be treated as Shape, but have different APIs
```javascript

## LSP Rules

A subclass violates LSP if it:

**Strengthens preconditions**: Requires more than parent

**Weakens postconditions**: Guarantees less than parent

**Throws new exceptions**: Parent doesn't throw them

**Changes behavior unexpectedly**: Acts differently than parent

## How to Follow LSP

**Design by Contract**: Child must honor parent's contract

**Behavioral Consistency**: Child behaves as parent promises

**No Surprising Changes**: Don't override with incompatible behavior

**Think "is-a"**: Only inherit if truly "is-a" relationship

## Key Takeaways

- **Child classes must be substitutable** for parent classes
- **Don't break parent's contract** or expectations
- **Inheritance should make sense** behaviorally, not just structurally
- **If substitution breaks code**, redesign the hierarchy

---

# Interface Segregation Principle (ISP)

The Interface Segregation Principle states that clients should not be forced to depend on interfaces they don't use. It's better to have many specific interfaces than one general-purpose interface.

## What is ISP?

**Interface Segregation Principle**: No client should be forced to depend on methods it doesn't use.

**Core Idea**: Many small, specific interfaces are better than one large, general interface

Think of a **remote control**:
- TV remote: Only TV controls
- AC remote: Only AC controls
- Universal remote with 100 buttons: Confusing and overwhelming
- Better: Separate remotes for each device

## Why ISP Matters

**Clarity**: Clear what each interface does

**Flexibility**: Implement only what you need

**Reduced Coupling**: Changes to unused methods don't affect you

**Easier Testing**: Test only relevant functionality

**Better Organization**: Logical grouping of related methods

## Violation Example

```javascript
// Bad - Fat interface, violates ISP
class Worker {
    work() {
        throw new Error("Must implement work()");
    }
    
    eat() {
        throw new Error("Must implement eat()");
    }
    
    sleep() {
        throw new Error("Must implement sleep()");
    }
    
    charge() {
        throw new Error("Must implement charge()");
    }
}

class HumanWorker extends Worker {
    work() {
        console.log("Human working");
    }
    
    eat() {
        console.log("Human eating");
    }
    
    sleep() {
        console.log("Human sleeping");
    }
    
    charge() {
        throw new Error("Humans don't charge!");  // Forced to implement
    }
}

class RobotWorker extends Worker {
    work() {
        console.log("Robot working");
    }
    
    eat() {
        throw new Error("Robots don't eat!");  // Forced to implement
    }
    
    sleep() {
        throw new Error("Robots don't sleep!");  // Forced to implement
    }
    
    charge() {
        console.log("Robot charging");
    }
}
```javascript

**Problem**: 
- HumanWorker forced to implement `charge()`
- RobotWorker forced to implement `eat()` and `sleep()`
- Both implement methods they don't need

## ISP Solution

```javascript
// Good - Segregated interfaces
class Workable {
    work() {
        throw new Error("Must implement work()");
    }
}

class Eatable {
    eat() {
        throw new Error("Must implement eat()");
    }
}

class Sleepable {
    sleep() {
        throw new Error("Must implement sleep()");
    }
}

class Chargeable {
    charge() {
        throw new Error("Must implement charge()");
    }
}

// Human implements only what it needs
class HumanWorker extends Workable {
    constructor() {
        super();
        this.eatable = new HumanEating();
        this.sleepable = new HumanSleeping();
    }
    
    work() {
        console.log("Human working");
    }
}

class HumanEating extends Eatable {
    eat() {
        console.log("Human eating");
    }
}

class HumanSleeping extends Sleepable {
    sleep() {
        console.log("Human sleeping");
    }
}

// Robot implements only what it needs
class RobotWorker extends Workable {
    constructor() {
        super();
        this.chargeable = new RobotCharging();
    }
    
    work() {
        console.log("Robot working");
    }
}

class RobotCharging extends Chargeable {
    charge() {
        console.log("Robot charging");
    }
}
```javascript

**Benefits**:
- Each class implements only relevant interfaces
- No forced implementation of unused methods
- Clear separation of concerns

## Real-World Example: Printer Interface

```javascript
// Bad - Fat interface
class Printer {
    print(document) { }
    scan(document) { }
    fax(document) { }
    staple(document) { }
}

class SimplePrinter extends Printer {
    print(document) {
        console.log("Printing");
    }
    
    scan(document) {
        throw new Error("Can't scan");  // Forced to implement
    }
    
    fax(document) {
        throw new Error("Can't fax");  // Forced to implement
    }
    
    staple(document) {
        throw new Error("Can't staple");  // Forced to implement
    }
}

// Good - Segregated interfaces
class Printable {
    print(document) { }
}

class Scannable {
    scan(document) { }
}

class Faxable {
    fax(document) { }
}

class Stapleable {
    staple(document) { }
}

// Simple printer only implements what it can do
class SimplePrinter extends Printable {
    print(document) {
        console.log("Printing");
    }
}

// Multi-function printer implements multiple interfaces
class MultiFunctionPrinter {
    constructor() {
        this.printable = new PrintFunction();
        this.scannable = new ScanFunction();
        this.faxable = new FaxFunction();
    }
}

class PrintFunction extends Printable {
    print(document) {
        console.log("Printing");
    }
}

class ScanFunction extends Scannable {
    scan(document) {
        console.log("Scanning");
    }
}

class FaxFunction extends Faxable {
    fax(document) {
        console.log("Faxing");
    }
}
```javascript

## Another Example: User Service

```javascript
// Bad - Fat interface
class UserService {
    createUser(user) { }
    deleteUser(id) { }
    updateUser(id, data) { }
    exportUsers() { }
    importUsers(data) { }
    sendEmailToUser(id) { }
    generateUserReport() { }
}

// Good - Segregated interfaces
class UserManagement {
    createUser(user) { }
    updateUser(id, data) { }
    deleteUser(id) { }
}

class UserDataExport {
    exportUsers() { }
    importUsers(data) { }
}

class UserCommunication {
    sendEmailToUser(id) { }
}

class UserReporting {
    generateUserReport() { }
}

// Clients use only what they need
class AdminPanel {
    constructor() {
        this.userManagement = new UserManagement();
        this.userReporting = new UserReporting();
    }
}

class DataMigrationTool {
    constructor() {
        this.userDataExport = new UserDataExport();
    }
}
```

## How to Apply ISP

**Identify Client Needs**: What does each client actually use?

**Group Related Methods**: Create interfaces for related functionality

**Keep Interfaces Small**: Fewer methods per interface

**Compose Interfaces**: Clients can use multiple small interfaces

## Benefits of ISP

```sql
┌────────────────────────────────────────────────────┐
│         Benefits of Interface Segregation           │
└────────────────────────────────────────────────────┘

Fat Interface              Segregated Interfaces
├─ Forced implementations  ├─ Implement only what's needed
├─ Confused purpose        ├─ Clear purpose
├─ Hard to maintain        ├─ Easy to maintain
├─ High coupling           ├─ Low coupling
└─ Brittle code            └─ Flexible code
```javascript

## Key Takeaways

- **Many small interfaces** > One large interface
- **Don't force clients** to implement unused methods
- **Keep interfaces focused** on specific functionality
- **Clients depend only** on what they actually use

---

# Dependency Inversion Principle (DIP)

The Dependency Inversion Principle states that high-level modules should not depend on low-level modules. Both should depend on abstractions.

## What is DIP?

**Dependency Inversion Principle**: 
1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
2. Abstractions should not depend on details. Details should depend on abstractions.

**Core Idea**: Depend on interfaces, not concrete implementations

Think of **electrical outlets**:
- Devices don't depend on specific power plants
- Both devices and power plants depend on the standard outlet interface
- You can switch power sources without changing devices

## Why DIP Matters

**Flexibility**: Easy to swap implementations

**Testability**: Mock dependencies for testing

**Loose Coupling**: High-level logic independent of low-level details

**Maintainability**: Changes to details don't affect high-level modules

**Reusability**: High-level modules can work with different implementations

## Violation Example

```javascript
// Bad - Violates DIP
class MySQLDatabase {
    connect() {
        console.log("Connecting to MySQL");
    }
    
    query(sql) {
        console.log(`Executing: ${sql}`);
    }
}

// High-level module depends on low-level concrete class
class UserService {
    constructor() {
        this.database = new MySQLDatabase();  // Direct dependency
    }
    
    getUser(id) {
        this.database.connect();
        this.database.query(`SELECT * FROM users WHERE id = ${id}`);
    }
}

// Problems:
// - UserService tightly coupled to MySQLDatabase
// - Can't easily switch to PostgreSQL or MongoDB
// - Hard to test without actual MySQL connection
```javascript

## DIP Solution

```javascript
// Good - Follows DIP

// Abstraction (interface)
class Database {
    connect() {
        throw new Error("Must implement connect()");
    }
    
    query(sql) {
        throw new Error("Must implement query()");
    }
}

// Low-level implementations depend on abstraction
class MySQLDatabase extends Database {
    connect() {
        console.log("Connecting to MySQL");
    }
    
    query(sql) {
        console.log(`MySQL query: ${sql}`);
    }
}

class PostgreSQLDatabase extends Database {
    connect() {
        console.log("Connecting to PostgreSQL");
    }
    
    query(sql) {
        console.log(`PostgreSQL query: ${sql}`);
    }
}

class MongoDatabase extends Database {
    connect() {
        console.log("Connecting to MongoDB");
    }
    
    query(sql) {
        console.log(`MongoDB query: ${sql}`);
    }
}

// High-level module depends on abstraction
class UserService {
    constructor(database) {
        this.database = database;  // Injected dependency
    }
    
    getUser(id) {
        this.database.connect();
        this.database.query(`SELECT * FROM users WHERE id = ${id}`);
    }
}

// Usage - easy to switch databases
const mysqlService = new UserService(new MySQLDatabase());
const postgresService = new UserService(new PostgreSQLDatabase());
const mongoService = new UserService(new MongoDatabase());

// Easy to test with mock
class MockDatabase extends Database {
    connect() { }
    query(sql) { return "mock data"; }
}

const testService = new UserService(new MockDatabase());
```

**Benefits**:
- UserService doesn't know which database it uses
- Easy to switch database implementations
- Easy to test with mocks
- Both high-level and low-level depend on abstraction

## Visual Understanding

```javascript
┌────────────────────────────────────────────────────┐
│       Without DIP (Bad)                             │
└────────────────────────────────────────────────────┘

    ┌──────────────┐
    │ UserService  │ (High-level)
    └──────┬───────┘
           │ depends on
           ▼
    ┌──────────────┐
    │ MySQLDatabase│ (Low-level concrete)
    └──────────────┘

Problem: High-level depends on low-level directly


┌────────────────────────────────────────────────────┐
│       With DIP (Good)                              │
└────────────────────────────────────────────────────┘

    ┌──────────────┐
    │ UserService  │ (High-level)
    └──────┬───────┘
           │ depends on
           ▼
    ┌──────────────┐
    │  <<Database>>│ (Abstraction)
    └──────△───────┘
           │ implements
           │
    ┌──────┴───────┬──────────────┐
    │              │              │
┌───┴───────┐ ┌────┴──────┐ ┌────┴──────┐
│  MySQL    │ │PostgreSQL │ │  MongoDB  │
│ Database  │ │ Database  │ │           │
└───────────┘ └───────────┘ └───────────┘
        (Low-level concrete)

Solution: Both depend on abstraction
```javascript

## Real-World Example: Notification System

```javascript
// Bad - Violates DIP
class EmailSender {
    send(message) {
        console.log(`Sending email: ${message}`);
    }
}

class NotificationService {
    constructor() {
        this.emailSender = new EmailSender();  // Tight coupling
    }
    
    notify(message) {
        this.emailSender.send(message);
    }
}

// Can't easily add SMS or Push notifications


// Good - Follows DIP
class MessageSender {
    send(message) {
        throw new Error("Must implement send()");
    }
}

class EmailSender extends MessageSender {
    send(message) {
        console.log(`Sending email: ${message}`);
    }
}

class SmsSender extends MessageSender {
    send(message) {
        console.log(`Sending SMS: ${message}`);
    }
}

class PushNotificationSender extends MessageSender {
    send(message) {
        console.log(`Sending push notification: ${message}`);
    }
}

// Depends on abstraction, not concrete implementation
class NotificationService {
    constructor(messageSender) {
        this.messageSender = messageSender;
    }
    
    notify(message) {
        this.messageSender.send(message);
    }
}

// Easy to switch or combine senders
const emailService = new NotificationService(new EmailSender());
const smsService = new NotificationService(new SmsSender());
const pushService = new NotificationService(new PushNotificationSender());
```sql

## Dependency Injection

DIP is often implemented using **Dependency Injection**:

```javascript
// Constructor Injection
class OrderService {
    constructor(paymentGateway, emailService) {
        this.paymentGateway = paymentGateway;
        this.emailService = emailService;
    }
    
    processOrder(order) {
        this.paymentGateway.charge(order.amount);
        this.emailService.sendConfirmation(order);
    }
}

// Dependencies injected from outside
const orderService = new OrderService(
    new StripePayment(),
    new EmailService()
);
```text

## Benefits of DIP

```
┌────────────────────────────────────────────────────┐
│         Benefits of Dependency Inversion           │
└────────────────────────────────────────────────────┘

Flexibility
└─ Easy to swap implementations

Testability
└─ Mock dependencies for testing

Loose Coupling
└─ Modules independent of each other

Maintainability
└─ Changes to low-level don't
affect high-level

Reusability
└─ High-level modules work with any implementation
```javascript

## Key Takeaways

- **Depend on abstractions**, not concrete implementations
- **High-level modules** should not depend on **low-level modules**
- **Use interfaces** to define contracts
- **Inject dependencies** instead of creating them
- **Both high and low-level** depend on abstractions
- **DIP enables flexibility** and testability

---

# SOLID Principles Summary

The SOLID principles work together to create maintainable, flexible, and scalable software:

## Principle Overview

| Principle | What It Says | Example |
|-----------|--------------|---------|
| **S**RP | One class, one responsibility | User class handles user data only |
| **O**CP | Open for extension, closed for modification | Add payment methods without modifying PaymentProcessor |
| **L**SP | Subtypes must be substitutable | Bird subclasses behave consistently |
| **I**SP | Many small interfaces > One fat interface | Separate Printable, Scannable interfaces |
| **D**IP | Depend on abstractions, not concrete classes | UserService depends on Database interface |

## How SOLID Principles Work Together

```javascript
Single Responsibility Principle
├─ Gives each class ONE clear responsibility
│
Open/Closed Principle
├─ Allows extension WITHOUT modification
│
Liskov Substitution Principle
├─ Ensures subclasses are truly substitutable
│
Interface Segregation Principle
├─ Keeps interfaces focused and specific
│
Dependency Inversion Principle
└─ Decouples high-level from low-level modules
```text

## Benefits of Following SOLID

**Maintainability**: Easy to understand and modify

**Flexibility**: Adapt to changing requirements

**Testability**: Easy to write unit tests

**Reusability**: Components can be reused

**Reduced Bugs**: Clear structure prevents errors

**Team Collaboration**: Consistent, predictable code

## When to Apply SOLID

**Always Consider**: Keep principles in mind during design

**Don't Over-Engineer**: Apply when it adds value, not complexity

**Refactor Gradually**: Improve existing code incrementally

**Balance**: Practical solutions over perfect adherence

These five principles are fundamental to writing high-quality object-oriented code. They work together to create systems that are easy to maintain, extend, and understand.

---

# UML (Unified Modeling Language)

UML is a standardized visual language for modeling software systems. It provides diagrams to represent the structure, behavior, and interactions of a system, making complex designs easier to understand and communicate.

## What is UML?

**UML (Unified Modeling Language)**: A visual modeling language used to design and document software systems.

**Core Idea**: Pictures are worth a thousand words - visualize before you build

Think of **building blueprints**:
- Architects draw blueprints before construction
- Blueprints show structure, layout, connections
- UML diagrams are blueprints for software

## Why UML Matters

**Visual Communication**: Easier to understand than text

**Team Collaboration**: Common language for developers, designers, stakeholders

**Design Clarity**: Think through design before coding

**Documentation**: Provides clear system documentation

**Problem Detection**: Catch design flaws early

## Types of UML Diagrams
```text
UML Diagrams
    │
    ├─ Structural Diagrams
    │   ├─ Class Diagram
    │   ├─ Object Diagram
    │   ├─ Component Diagram
    │   └─ Deployment Diagram
    │
    └─ Behavioral Diagrams
        ├─ Use Case Diagram
        ├─ Sequence Diagram
        ├─ Activity Diagram
        ├─ State Diagram
        └─ Collaboration Diagram
```javascript

We'll focus on the four most commonly used diagrams in Low-Level Design.

### Diagram Selection Guide
```mermaid
flowchart TD
    A[What do you need to explain?] --> B[Structure]
    A --> C[Behavior]
    B --> D[Class Diagram]
    B --> E[Component/Deployment Diagram]
    C --> F[Use Case Diagram]
    C --> G[Sequence Diagram]
    C --> H[Activity Diagram]
```

---

# Class Diagram

Class diagrams show the static structure of a system by displaying classes, their attributes, methods, and relationships between classes.

## What is a Class Diagram?

**Class Diagram**: Shows classes and their relationships in the system.

**Purpose**: Visualize the structure of classes and how they interact

Think of an **organizational chart**:
- Shows departments (classes)
- Shows roles within departments (attributes/methods)
- Shows relationships between departments (associations)

## Basic Elements

### 1. Class Representation
```text
┌─────────────────────────┐
│      ClassName          │ ← Class Name
├─────────────────────────┤
│ - attribute1: Type      │ ← Attributes (fields)
│ - attribute2: Type      │
│ # attribute3: Type      │
├─────────────────────────┤
│ + method1(): ReturnType │ ← Methods
│ + method2(param): Type  │
│ - method3(): void       │
└─────────────────────────┘
```

### Example Class Diagram (Mermaid)
```mermaid
classDiagram
    class User {
        +String id
        +String name
        +login()
    }
    class Order {
        +String id
        +place()
    }
    User "1" --> "*" Order : places
```

**Visibility Symbols**:
```javascript
+ Public    (accessible everywhere)
- Private   (accessible only within class)
# Protected (accessible within class and subclasses)
~ Package   (accessible within package)
```text

### 2. Example: User Class
```text
┌─────────────────────────┐
│         User            │
├─────────────────────────┤
│ - userId: String        │
│ - name: String          │
│ - email: String         │
│ - password: String      │
├─────────────────────────┤
│ + login(): boolean      │
│ + logout(): void        │
│ + updateProfile(): void │
│ - validateEmail(): bool │
└─────────────────────────┘
```

## Relationships in Class Diagrams

### 1. Association (uses)

Simple relationship between classes.
```text
┌──────────┐           ┌──────────┐
│ Teacher  │ ────────> │ Student  │
└──────────┘           └──────────┘
    1                      0..*

Teacher teaches Students
```text

### 2. Aggregation (has-a, weak)

Whole-part relationship where part can exist independently.
```text
┌────────────┐           ┌───────────┐
│ Department │ ◇────────>│ Professor │
└────────────┘           └───────────┘
    1                      0..*

Department has Professors (professors can exist without department)
```

### 3. Composition (has-a, strong)

Whole-part relationship where part cannot exist independently.
```text
┌───────┐           ┌──────┐
│ House │ ◆────────>│ Room │
└───────┘           └──────┘
   1                 1..*

House has Rooms (rooms destroyed with house)
```text

### 4. Inheritance (is-a)

Parent-child relationship.
```text
        ┌─────────┐
        │ Animal  │
        └────△────┘
             │
        ┌────┴────┐
        │         │
   ┌────┴───┐ ┌──┴────┐
   │  Dog   │ │  Cat  │
   └────────┘ └───────┘

Dog is an Animal, Cat is an Animal
```

### 5. Realization (implements)

Class implements an interface.
```javascript
┌──────────────────┐
│  <<interface>>   │
│  PaymentGateway  │
└────────△─────────┘
         │
    ┌────┴────┐
    │         │
┌───┴───┐ ┌──┴────┐
│Stripe │ │PayPal │
└───────┘ └───────┘

Stripe implements PaymentGateway
```javascript

### 6. Dependency (uses temporarily)

One class uses another temporarily.
```text
┌──────────┐           ┌───────────┐
│  User    │ - - - - > │ EmailUtil │
└──────────┘           └───────────┘

User depends on EmailUtil (temporary usage)
```text

## Multiplicity (Cardinality)

Shows how many instances are involved in a relationship.
```
1       Exactly one
0..1    Zero or one
0..*    Zero or more
1..*    One or more
*       Many
n       Specific number (e.g., 5)
1..n    Range (e.g., 1 to 10)
```text

## Real-World Example: Library System
```text
┌─────────────────────┐
│      Library        │
└──────────┬──────────┘
           │ 1
           │
           │ *
           │
┌──────────▼──────────┐           ┌─────────────────┐
│       Book          │           │     Member      │
├─────────────────────┤           ├─────────────────┤
│ - isbn: String      │           │ - memberId: int │
│ - title: String     │ *    *    │ - name: String  │
│ - author: String    │◄─────────►│ - email: String │
│ - isAvailable: bool │  borrows  ├─────────────────┤
├─────────────────────┤           │ + borrowBook()  │
│ + checkOut(): void  │           │ + returnBook()  │
│ + checkIn(): void   │           └─────────────────┘
└─────────────────────┘

Relationships:
- Library has many Books (composition)
- Member borrows many Books (association)
- Book is borrowed by many Members (association)
```text

## E-commerce Example
```
┌─────────────────┐
│    Customer     │
├─────────────────┤
│ - customerId    │
│ - name          │
│ - email         │
├─────────────────┤
│ + placeOrder()  │
└────────┬────────┘
         │ 1
         │
         │ *
         ▼
┌─────────────────┐         ┌──────────────┐
│     Order       │         │   Product    │
├─────────────────┤         ├──────────────┤
│ - orderId       │   *  *  │ - productId  │
│ - orderDate     │◄───────►│ - name       │
│ - totalAmount   │contains │ - price      │
├─────────────────┤         ├──────────────┤
│ + addItem()     │         │ + getPrice() │
│ + calculate()   │         └──────────────┘
└─────────────────┘
```javascript

## When to Use Class Diagrams

**System Design**: Plan class structure before coding

**Documentation**: Document existing system architecture

**Team Communication**: Discuss design with team

**Refactoring**: Visualize changes to class structure

## Key Takeaways

- **Shows static structure** of the system
- **Displays classes**, attributes, methods, relationships
- **Multiple relationship types**: association, aggregation, composition, inheritance
- **Essential for** designing and documenting systems

---

# Use Case Diagram

Use case diagrams show how users (actors) interact with the system. They describe what the system does from the user's perspective.

## What is a Use Case Diagram?

**Use Case Diagram**: Shows interactions between users (actors) and system functionalities (use cases).

**Purpose**: Capture functional requirements from user's viewpoint

Think of a **restaurant menu**:
- Customers (actors) can order dishes (use cases)
- Menu shows what customers can do
- Use case diagram shows what users can do with the system

## Basic Elements

### 1. Actor

Represents a user or external system.
```javascript
    ┌─┐
    │ │  ← Stick figure represents actor
    └┬┘
     │
    ┌┴┐

Examples: Customer, Admin, Payment System
```javascript

### 2. Use Case

Represents a system function or feature.
```text
    ╱────────────╲
   │  Use Case   │  ← Oval represents use case
    ╲────────────╱

Examples: Login, Place Order, Generate Report
```text

### 3. System Boundary

Box that contains all use cases.
```
┌─────────────────────────────┐
│      System Name            │
│                             │
│  ╱──────────╲              │
│ │ Use Case 1│              │
│  ╲──────────╱              │
│                             │
│  ╱──────────╲              │
│ │ Use Case 2│              │
│  ╲──────────╱              │
└─────────────────────────────┘
```javascript

### 4. Relationships

**Association**: Actor interacts with use case (solid line)
**Include**: Use case always includes another (dashed arrow with <<include>>)
**Extend**: Use case optionally extends another (dashed arrow with <<extend>>)
**Generalization**: Inheritance between actors or use cases (solid arrow)

## Simple Example: ATM System
```text
                        ┌───────────────────────────────┐
                        │        ATM System             │
                        │                               │
    ┌─┐                 │   ╱─────────────────╲        │
    │ │ Customer ──────────│  Withdraw Cash    │        │
    └┬┘                 │   ╲─────────────────╱        │
     │                  │           │                   │
    ┌┴┐                 │           │ <<include>>       │
                        │           ▼                   │
                        │   ╱─────────────────╲        │
                        │  │  Verify PIN       │        │
                        │   ╲─────────────────╱        │
                        │                               │
                        │   ╱─────────────────╲        │
    Customer ──────────────│  Check Balance    │        │
                        │   ╲─────────────────╱        │
                        │           │                   │
                        │           │ <<include>>       │
                        │           ▼                   │
                        │   ╱─────────────────╲        │
                        │  │  Verify PIN       │        │
                        │   ╲─────────────────╱        │
                        │                               │
                        │   ╱─────────────────╲        │
    Customer ──────────────│  Deposit Money    │        │
                        │   ╲─────────────────╱        │
                        │                               │
                        └───────────────────────────────┘

Legend:
- Customer is the actor (user of the system)
- Withdraw Cash, Check Balance, Deposit Money are use cases
- Verify PIN is included in multiple use cases
```text

## E-commerce Example
```text
                    ┌────────────────────────────────────────┐
                    │     E-commerce System                  │
  ┌─┐               │                                        │
  │ │ Customer ────────╱──────────────╲                     │
  └┬┘               │  │ Browse Products│                     │
   │                │   ╲──────────────╱                     │
  ┌┴┐               │                                        │
                    │   ╱──────────────╲                     │
  Customer ────────────│  Add to Cart   │                     │
                    │   ╲──────────────╱                     │
                    │                                        │
                    │   ╱──────────────╲                     │
  Customer ────────────│  Checkout      │                     │
                    │   ╲──────┬───────╱                     │
                    │          │                             │
                    │          │ <<include>>                 │
                    │          ▼                             │
                    │   ╱──────────────╲                     │
                    │  │ Process Payment│                     │
                    │   ╲──────────────╱                     │
                    │                                        │
                    │   ╱──────────────╲                     │
  Customer ────────────│  Track Order   │                     │
                    │   ╲──────────────╱                     │
                    │                                        │
  ┌─┐               │   ╱──────────────╲                     │
  │ │ Admin ───────────│ Manage Products│                     │
  └┬┘               │   ╲──────────────╱                     │
   │                │                                        │
  ┌┴┐               │   ╱──────────────╲                     │
                    │  │ View Reports   │                     │
  Admin ───────────────╲──────────────╱                     │
                    │                                        │
                    └────────────────────────────────────────┘
```

## Include vs Extend

### Include (<<include>>)

Base use case always includes the included use case.
```text
   ╱────────────╲
  │ Place Order │
   ╲──────┬─────╱
          │ <<include>>
          ▼
   ╱────────────╲
  │Validate Cart│
   ╲────────────╱

Every time you place an order, cart validation happens
```text

### Extend (<<extend>>)

Extended use case optionally adds behavior to base use case.
```text
   ╱────────────╲
  │    Login    │
   ╲──────△─────╱
          │ <<extend>>
          │
   ╱──────┴─────╲
  │ Remember Me │
   ╲────────────╱

Login can optionally include "Remember Me" feature
```

## Real-World Example: Online Banking
```text
                    ┌────────────────────────────────────────┐
                    │     Online Banking System              │
  ┌─┐               │                                        │
  │ │ User ────────────╱──────────────╲                     │
  └┬┘               │  │    Login      │                     │
   │                │   ╲──────┬───────╱                     │
  ┌┴┐               │          │                             │
                    │          │ <<include>>                 │
                    │          ▼                             │
                    │   ╱──────────────╲                     │
                    │  │ Authenticate  │                     │
                    │   ╲──────────────╱                     │
                    │                                        │
                    │   ╱──────────────╲                     │
  User ────────────────│ View Balance  │                     │
                    │   ╲──────────────╱                     │
                    │                                        │
                    │   ╱──────────────╲                     │
  User ────────────────│Transfer Funds │                     │
                    │   ╲──────┬───────╱                     │
                    │          │                             │
                    │          │ <<include>>                 │
                    │          ▼                             │
                    │   ╱──────────────╲                     │
                    │  │ Verify Account│                     │
                    │   ╲──────────────╱                     │
                    │                                        │
                    │   ╱──────────────╲                     │
  User ────────────────│  Pay Bills    │◄─────────────────  │
                    │   ╲──────────────╱  <<extend>>        │
                    │                     ╱──────────────╲  │
                    │                    │Schedule Payment│  │
                    │                     ╲──────────────╱  │
                    │                                        │
                    └────────────────────────────────────────┘
```text

## When to Use Use Case Diagrams

**Requirements Gathering**: Understand what users need

**System Planning**: Define system scope and features

**Communication**: Explain system to stakeholders

**Testing**: Basis for creating test cases

## Key Takeaways

- **Shows functional requirements** from user perspective
- **Actors** interact with **use cases**
- **Include** for mandatory sub-functionality
- **Extend** for optional functionality
- **Useful for** requirements and planning

---

# Sequence Diagram

Sequence diagrams show how objects interact with each other over time. They display the sequence of messages exchanged between objects.

## What is a Sequence Diagram?

**Sequence Diagram**: Shows interactions between objects in a time-ordered sequence.

**Purpose**: Visualize the flow of messages and method calls

Think of a **phone conversation**:
- Shows who speaks when
- Shows the order of messages
- Shows responses and timing

## Basic Elements

### 1. Actor/Object
```text
   ┌─┐
   │ │  ← Actor (user)
   └┬┘
    │

┌─────────┐
│ Object  │ ← Object/Class
└────┬────┘
     │
```text

### 2. Lifeline

Vertical dashed line showing object's lifetime.
```
┌─────────┐
│ Object  │
└────┬────┘
     │ ← Lifeline (dashed vertical line)
     │
     │
```text

### 3. Activation Box

Shows when object is active/processing.
```text
┌─────────┐
│ Object  │
└────┬────┘
     │
     ├─┐ ← Activation box (thin rectangle)
     │ │
     │ │
     ├─┘
     │
```text

### 4. Messages

Arrows showing communication between objects.
```
─────────> Synchronous message (solid line, filled arrow)
- - - - -> Asynchronous message (dashed line, open arrow)
<────────  Return message (dashed line, open arrow)
```text

## Simple Example: User Login
```text
  User          LoginPage        AuthService      Database
   │                │                 │               │
   │   enterCreds() │                 │               │
   │───────────────>│                 │               │
   │                │   validate()    │               │
   │                │────────────────>│               │
   │                │                 │  checkUser()  │
   │                │                 │──────────────>│
   │                │                 │               │
   │                │                 │  user data    │
   │                │                 │<──────────────│
   │                │   valid/invalid │               │
   │                │<────────────────│               │
   │  show result   │                 │               │
   │<───────────────│                 │               │
   │                │                 │               │
```text

## E-commerce Example: Place Order
```
Customer    ShoppingCart    OrderService    PaymentGateway    Database
   │             │               │                │              │
   │ checkout()  │               │                │              │
   │────────────>│               │                │              │
   │             │ createOrder() │                │              │
   │             │──────────────>│                │              │
   │             │               │ validateOrder()│              │
   │             │               │────────┐       │              │
   │             │               │        │       │              │
   │             │               │<───────┘       │              │
   │             │               │ processPayment()              │
   │             │               │───────────────>│              │
   │             │               │                │ charge()     │
   │             │               │                │──────────┐   │
   │             │               │                │          │   │
   │             │               │                │<─────────┘   │
   │             │               │   success      │              │
   │             │               │<───────────────│              │
   │             │               │  saveOrder()   │              │
   │             │               │─────────────────────────────>│
   │             │               │                │  order saved │
   │             │               │<──────────────────────────────│
   │             │  orderConfirm │                │              │
   │             │<──────────────│                │              │
   │confirmation │               │                │              │
   │<────────────│               │                │              │
   │             │               │                │              │
```text

## ATM Withdrawal Example
```text
Customer      ATM        BankSystem    Database    CashDispenser
   │           │              │            │             │
   │insertCard │              │            │             │
   │──────────>│              │            │             │
   │           │              │            │             │
   │ enterPIN  │              │            │             │
   │──────────>│              │            │             │
   │           │ verifyPIN()  │            │             │
   │           │─────────────>│            │             │
   │           │              │ checkPIN() │             │
   │           │              │───────────>│             │
   │           │              │  verified  │             │
   │           │              │<───────────│             │
   │           │  PIN valid   │            │             │
   │           │<─────────────│            │             │
   │           │              │            │             │
   │ withdraw  │              │            │             │
   │──────────>│              │            │             │
   │           │ checkBalance()            │             │
   │           │─────────────>│            │             │
   │           │              │getBalance()│             │
   │           │              │───────────>│             │
   │           │              │  balance   │             │
   │           │              │<───────────│             │
   │           │   sufficient │            │             │
   │           │<─────────────│            │             │
   │           │              │            │             │
   │           │          updateBalance()  │             │
   │           │─────────────>│            │             │
   │           │              │   save()   │             │
   │           │              │───────────>│             │
   │           │              │            │             │
   │           │         dispenseCash()                  │
   │           │──────────────────────────────────────>│
   │           │              │            │             │
   │takeCash   │              │            │             │
   │<──────────│              │            │             │
   │           │              │            │             │
```text

## Loop and Conditional

### Loop
```
OrderService    InventoryService
      │                │
      │                │
      ├─────loop [for each item]─────┐
      │                │              │
      │ checkStock()   │              │
      │───────────────>│              │
      │   available    │              │
      │<───────────────│              │
      │                │              │
      └────────────────────────────────┘
      │                │
```text

### Conditional (alt)
```sql
User        PaymentService
 │                │
 │  makePayment() │
 │───────────────>│
 │                │
 ├─alt [if credit card]─────┐
 │                │          │
 │                │chargeCreditCard()
 │                │          │
 ├─[else if PayPal]─────────┤
 │                │          │
 │                │processPayPal()
 │                │          │
 ├─[else]───────────────────┤
 │                │          │
 │    error       │          │
 │<───────────────│          │
 └────────────────────────────┘
 │                │
```text

## When to Use Sequence Diagrams

**Design Workflows**: Plan complex interactions

**Understand Existing Code**: Visualize flow of existing system

**Communication**: Explain process to team

**Documentation**: Document how system works

## Key Takeaways

- **Shows time-ordered interactions** between objects
- **Messages flow** from left to right, top to bottom
- **Activation boxes** show when objects are active
- **Useful for** understanding workflows and processes

---

# Activity Diagram

Activity diagrams show the flow of activities or actions in a system. They're similar to flowcharts and show the sequence of operations.

## What is an Activity Diagram?

**Activity Diagram**: Shows the workflow of activities and actions in a process.

**Purpose**: Visualize business processes and algorithms

Think of a **recipe**:
- Step-by-step instructions
- Decision points (if mixture is too thick, add water)
- Parallel actions (while baking, prepare frosting)

## Basic Elements

### 1. Start and End Nodes
```text
    ●  ← Start (filled circle)

    ◉  ← End (filled circle with border)
```

### 2. Activity/Action
```text
┌──────────────┐
│   Activity   │ ← Rounded rectangle
└──────────────┘
```text

### 3. Decision Node
```text
      ◇  ← Diamond (decision point)
     / \
    /   \
```

### 4. Fork and Join (Parallel Activities)
```text
━━━━━━━  ← Fork (thick horizontal line - splits into parallel)

━━━━━━━  ← Join (thick horizontal line - merges from parallel)
```text

### 5. Swimlanes

Vertical or horizontal partitions showing who does what.
```text
┌──────────┬──────────┬──────────┐
│Customer  │  System  │  Admin   │
├──────────┼──────────┼──────────┤
│          │          │          │
│          │          │          │
└──────────┴──────────┴──────────┘
```

## Simple Example: User Registration
```text
                    ●  Start
                    │
                    ▼
            ┌───────────────┐
            │  Fill Form    │
            └───────┬───────┘
                    │
                    ▼
                    ◇  Valid data?
                   / \
                  /   \
            [No] /     \ [Yes]
                /       \
               ▼         ▼
        ┌──────────┐  ┌──────────────┐
        │Show Error│  │ Create Account│
        └─────┬────┘  └───────┬───────┘
              │               │
              │               ▼
              │       ┌──────────────┐
              │       │Send Welcome  │
              │       │    Email     │
              │       └───────┬──────┘
              │               │
              └───────┬───────┘
                      │
                      ▼
              ┌──────────────┐
              │Show Confirmation│
              └───────┬──────┘
                      │
                      ▼
                      ◉  End
```text

## E-commerce Order Processing
```text
                        ●  Start
                        │
                        ▼
                ┌──────────────┐
                │ Browse Items │
                └──────┬───────┘
                       │
                       ▼
                ┌──────────────┐
                │ Add to Cart  │
                └──────┬───────┘
                       │
                       ▼
                ┌──────────────┐
                │   Checkout   │
                └──────┬───────┘
                       │
                       ▼
                       ◇  Payment valid?
                      / \
                     /   \
              [No]  /     \ [Yes]
                   /       \
                  ▼         ▼
          ┌───────────┐  ━━━━━━━━━━  Fork
          │Retry/Cancel│      │
          └──────┬────┘   ┌───┼───┐
                 │        │   │   │
                 │        ▼   ▼   ▼
                 │   ┌────────┐ ┌────────┐ ┌────────┐
                 │   │Process │ │Reserve │ │Send    │
                 │   │Payment │ │Stock   │ │Email   │
                 │   └───┬────┘ └───┬────┘ └───┬────┘
                 │       │          │          │
                 │       └────┬─────┴──────────┘
                 │            │
                 │        ━━━━━━━━━━  Join
                 │            │
                 │            ▼
                 │    ┌──────────────┐
                 │    │Generate Order│
                 │    └──────┬───────┘
                 │           │
                 └───────┬───┘
                         │
                         ▼
                 ┌──────────────┐
                 │ Show Success │
                 └──────┬───────┘
                        │
                        ▼
                        ◉  End
```

## ATM Withdrawal with Swimlanes
```text
┌────────────┬─────────────┬──────────────┐
│  Customer  │     ATM     │ Bank System  │
├────────────┼─────────────┼──────────────┤
│            │             │              │
│     ●      │             │              │
│     │      │             │              │
│     ▼      │             │              │
│ ┌────────┐ │             │              │
│ │Insert  │ │             │              │
│ │Card    │ │             │              │
│ └───┬────┘ │             │              │
│     │      │      ●      │              │
│     │      │      │      │              │
│     │      │      ▼      │              │
│     │      │  ┌────────┐ │              │
│     │      │  │Request │ │              │
│     │      │  │  PIN   │ │              │
│     │      │  └───┬────┘ │              │
│     ▼      │      │      │              │
│ ┌────────┐ │      │      │              │
│ │Enter   │ │      │      │              │
│ │ PIN    │ │      │      │              │
│ └───┬────┘ │      │      │              │
│     │      │      ▼      │              │
│     │      │  ┌────────┐ │      ●       │
│     │      │  │Send PIN│─┼─────>│       │
│     │      │  └────────┘ │      ▼       │
│     │      │             │  ┌────────┐  │
│     │      │             │  │Verify  │  │
│     │      │             │  │  PIN   │  │
│     │      │             │  └───┬────┘  │
│     │      │             │      │       │
│     │      │      ●      │      ◇       │
│     │      │      │      │<─────┤       │
│     │      │      │      │   Valid?     │
│     │      │      │      │     / \      │
│     │      │      │      │[No]/   \[Yes]│
│     │      │      ▼      │   /     \    │
│     │      │  ┌────────┐ │  ▼       ▼   │
│     │      │  │ Show   │ │ Eject  Proceed
│     │      │  │ Error  │ │ Card     │   │
│     │      │  └───┬────┘ │  │       │   │
│     │      │      ◉      │  ◉       │   │
│     ▼      │             │          ▼   │
│ ┌────────┐ │             │      ┌────────┐
│ │Select  │ │             │      │Check   │
│ │Amount  │ │             │      │Balance │
│ └───┬────┘ │             │      └───┬────┘
│     │      │      ●      │          │     │
│     │      │      │<─────┼──────────┘     │
│     │      │      ▼      │                │
│     │      │  ┌────────┐ │      ◇         │
│     │      │  │Process │ │  Sufficient?   │
│     │      │  │Request │ │     / \        │
│     │      │  └───┬────┘ │[No]/   \[Yes]  │
│     │      │      │      │   /     \      │
│     │      │      ▼      │  ▼       ▼     │
│     │      │  ┌────────┐ │ Error  Dispense│
│     │      │  │Dispense│ │  │      Cash   │
│     │      │  │  Cash  │ │  │       │     │
│     │      │  └───┬────┘ │  │       │     │
│     ▼      │      │      │  │       │     │
│ ┌────────┐ │      │      │  │       │     │
│ │Take    │ │      │      │  │       │     │
│ │Cash    │ │      │      │  │       │     │
│ └───┬────┘ │      │      │  │       │     │
│     │      │      ▼      │  ▼       ▼     │
│     │      │  ┌────────┐ │      ┌────────┐
│     │      │  │Print   │ │      │Update  │
│     │      │  │Receipt │ │      │Balance │
│     │      │  └───┬────┘ │      └───┬────┘
│     ▼      │      │      │          │     │
│ ┌────────┐ │      │      │          │     │
│ │Take    │ │      │      │          │     │
│ │Receipt │ │      │      │          │     │
│ └───┬────┘ │      │      │          │     │
│     │      │      ▼      │          ▼     │
│     ▼      │      ◉      │          ◉     │
│     ◉      │             │                │
│            │             │                │
└────────────┴─────────────┴────────────────┘
```text

## Online Shopping with Parallel Activities
```text
                    ●  Start
                    │
                    ▼
            ┌──────────────┐
            │Browse Products│
            └──────┬────────┘
                   │
                   ▼
            ┌──────────────┐
            │ Add to Cart  │
            └──────┬────────┘
                   │
                   ▼
                   ◇  Continue shopping?
                  / \
            [Yes]/   \[No]
                /     \
               │       ▼
               │   ┌──────────────┐
               │   │   Checkout   │
               │   └──────┬────────┘
               │          │
               └──────────┘
                          │
                          ▼
                   ━━━━━━━━━━  Fork
                      │
        ┌─────────────┼─────────────┐
        │             │             │
        ▼             ▼             ▼
┌──────────────┐ ┌──────────┐ ┌──────────┐
│Process       │ │Reserve   │ │Calculate │
│Payment       │ │Inventory │ │Shipping  │
└──────┬───────┘ └─────┬────┘ └─────┬────┘
       │               │            │
       └───────┬───────┴────────────┘
               │
           ━━━━━━━━━━  Join
               │
               ▼
               ◇  All successful?
              / \
        [No] /   \ [Yes]
            /     \
           ▼       ▼
    ┌──────────┐  ┌──────────────┐
    │Rollback  │  │Create Order  │
    │& Refund  │  └──────┬───────┘
    └────┬─────┘         │
         │               ▼
         │       ┌──────────────┐
         │       │Send          │
         │       │Confirmation  │
         │       └──────┬───────┘
         │              │
         └──────┬───────┘
                │
                ▼
                ◉  End
```

## Student Enrollment Process
```text
        ●  Start
        │
        ▼
┌──────────────┐
│Submit        │
│Application   │
└──────┬───────┘
       │
       ▼
       ◇  Documents complete?
      / \
[No] /   \ [Yes]
    /     \
   ▼       ▼
┌────────┐ ┌──────────────┐
│Request │ │Review         │
│Missing │ │Application    │
│Docs    │ └──────┬────────┘
└───┬────┘        │
    │             ▼
    │             ◇  Approved?
    │            / \
    │      [No] /   \ [Yes]
    │          /     \
    │         ▼       ▼
    │  ┌──────────┐  ┌──────────────┐
    │  │Send      │  │Send Admission│
    │  │Rejection │  │Letter        │
    │  └────┬─────┘  └──────┬───────┘
    │       │               │
    │       │               ▼
    │       │       ┌──────────────┐
    │       │       │Schedule      │
    │       │       │Orientation   │
    │       │       └──────┬───────┘
    │       │              │
    │       │              ▼
    │       │       ┌──────────────┐
    │       │       │Enroll in     │
    │       │       │Classes       │
    │       │       └──────┬───────┘
    │       │              │
    │       ▼              ▼
    │       ◉              ◉
    │
    └───(Loop back to start)
```text

## Decision with Multiple Paths
```text
                ●  Start
                │
                ▼
        ┌──────────────┐
        │ Check Weather│
        └──────┬───────┘
               │
               ▼
               ◇  Condition?
              /│\
             / │ \
            /  │  \
      Sunny/   │   \Rainy
          /    │    \
         /  Cloudy   \
        ▼      │      ▼
┌──────────┐   │  ┌──────────┐
│Go to     │   │  │Stay Home │
│Beach     │   │  └────┬─────┘
└────┬─────┘   │       │
     │         ▼       │
     │  ┌──────────┐   │
     │  │Go to Park│   │
     │  └────┬─────┘   │
     │       │         │
     └───┬───┴─────────┘
         │
         ▼
 ┌──────────────┐
 │ Enjoy Day    │
 └──────┬───────┘
        │
        ▼
        ◉  End
```

## Loop Example: Process All Items
```text
            ●  Start
            │
            ▼
    ┌──────────────┐
    │Get Item List │
    └──────┬───────┘
           │
           ▼
           ◇  More items?
          / \
    [No] /   \ [Yes]
        /     \
       /       ▼
      /  ┌──────────────┐
     /   │Process Item  │
    /    └──────┬───────┘
   /            │
  /             ▼
 /        ┌──────────────┐
│         │Validate Item │
│         └──────┬───────┘
│                │
│                ▼
│                ◇  Valid?
│               / \
│         [No] /   \ [Yes]
│             /     \
│            ▼       ▼
│     ┌──────────┐  ┌──────────┐
│     │Log Error │  │Add to    │
│     └────┬─────┘  │Results   │
│          │        └────┬─────┘
│          │             │
│          └─────┬───────┘
│                │
└────────────────┘ (Loop back)
                 │
                 ▼
         ┌──────────────┐
         │Generate      │
         │Summary Report│
         └──────┬───────┘
                │
                ▼
                ◉  End
```text

## When to Use Activity Diagrams

**Business Processes**: Model workflows and procedures

**Algorithm Design**: Visualize complex logic

**Use Case Details**: Show detailed steps within a use case

**Parallel Processing**: Show concurrent activities

**Decision Logic**: Visualize branching and conditions

## Activity Diagram vs Flowchart
```text
┌────────────────────────────────────────────────────┐
│      Activity Diagram vs Flowchart                 │
└────────────────────────────────────────────────────┘

Flowchart                  Activity Diagram
├─ Simple process flow     ├─ Complex business processes
├─ Algorithm logic         ├─ Parallel activities
├─ Code-level detail       ├─ High-level workflows
└─ Single path focus       └─ Multiple actors (swimlanes)
```text

## Key Takeaways

- **Shows workflow** and sequence of activities
- **Decision points** show branching logic
- **Fork/Join** show parallel activities
- **Swimlanes** show who does what
- **Useful for** business processes and complex workflows

---

# UML Diagrams Summary
```
┌────────────────────────────────────────────────────┐
│              UML Diagrams Overview                  │
└────────────────────────────────────────────────────┘

Class Diagram
├─ Purpose: Show system structure
├─ Shows: Classes, attributes, methods, relationships
└─ When: Design phase, documentation

Use Case Diagram
├─ Purpose: Show system functionality
├─ Shows: Actors, use cases, interactions
└─ When: Requirements gathering, planning

Sequence Diagram
├─ Purpose: Show object interactions over time
├─ Shows: Objects, messages, lifelines
└─ When: Design workflows, understand flow

Activity Diagram
├─ Purpose: Show process flow
├─ Shows: Activities, decisions, parallel paths
└─ When: Business processes, algorithms
```text

## Choosing the Right Diagram
```sql
What do you need to show?

Static Structure
└─> Use Class Diagram

User Interactions
└─> Use Use Case Diagram

Message Flow
└─> Use Sequence Diagram

Process/Workflow
└─> Use Activity Diagram
```text

## Benefits of UML

**Visual Communication**: Easier than text descriptions

**Standard Language**: Everyone understands the notation

**Early Problem Detection**: Catch design issues before coding

**Documentation**: Clear system documentation

**Team Collaboration**: Common understanding across team

## When to Use UML

**Planning Phase**: Design before implementation

**Communication**: Explain system to stakeholders

**Documentation**: Document existing systems

**Complex Systems**: Visualize intricate relationships

**Team Projects**: Ensure shared understanding

## Key Takeaways

- **UML provides standard visual notation** for software design
- **Class diagrams** show structure
- **Use case diagrams** show functionality
- **Sequence diagrams** show interactions over time
- **Activity diagrams** show workflows and processes
- **Choose the right diagram** for what you need to communicate

Each diagram serves a specific purpose and together they provide a complete picture of your system's design.

---

# Introduction to Design Patterns

Design patterns are reusable solutions to commonly occurring problems in software design. They represent best practices evolved over time by experienced developers and provide a template for how to solve problems that can be used in many different situations.

## What are Design Patterns?

**Design Pattern**: A general, reusable solution to a commonly occurring problem within a given context in software design.

**Core Idea**: Don't reinvent the wheel - use proven solutions to common problems

Think of **architectural blueprints**:
- Architects don't design every building from scratch
- They use proven patterns: arches for doorways, columns for support
- Design patterns are blueprints for code

## Why Design Patterns Matter

**Proven Solutions**: Battle-tested approaches that work

**Common Vocabulary**: Team members can communicate using pattern names

**Best Practices**: Encapsulate expert knowledge

**Faster Development**: Don't waste time solving solved problems

**Maintainability**: Well-known patterns are easier to understand

**Flexibility**: Make systems more adaptable to change

## History of Design Patterns

Design patterns in software were popularized by the "Gang of Four" (GoF). Their 1994 book documented 23 classic patterns that are still widely used today.

## Categories of Design Patterns
```text
┌────────────────────────────────────────────────────┐
│           Design Pattern Categories                 │
└────────────────────────────────────────────────────┘

Creational Patterns
├─ Deal with object creation
├─ Make systems independent of how objects are created
└─ Examples: Singleton, Factory, Builder

Structural Patterns
├─ Deal with object composition
├─ Define relationships between objects
└─ Examples: Adapter, Decorator, Facade

Behavioral Patterns
├─ Deal with object collaboration
├─ Define how objects interact and communicate
└─ Examples: Strategy, Observer, Command
```

### Pattern Selection Flow
```mermaid
flowchart TD
    A[What problem are you solving?] --> B[Object creation]
    A --> C[Object composition]
    A --> D[Object interaction]
    B --> E[Creational Patterns]
    C --> F[Structural Patterns]
    D --> G[Behavioral Patterns]
```

## The Three Categories Explained

### 1. Creational Patterns

**Purpose**: Control object creation mechanisms

**Problem They Solve**: How to create objects in a way that's flexible and reusable

**Focus**: Object instantiation

**Common Patterns**:
```text
Singleton
├─ Ensure only one instance exists
└─ Example: Database connection, Logger

Factory Method
├─ Create objects without specifying exact class
└─ Example: Document creator (PDF, Word, HTML)

Builder
├─ Construct complex objects step by step
└─ Example: Building a meal (burger, drink, fries)

Abstract Factory
├─ Create families of related objects
└─ Example: UI components for different themes

Prototype
├─ Clone existing objects
└─ Example: Copying game characters
```

### 2. Structural Patterns

**Purpose**: Organize classes and objects into larger structures

**Problem They Solve**: How to compose objects to form flexible structures

**Focus**: Object relationships and composition

**Common Patterns**:
```sql
Adapter
├─ Make incompatible interfaces work together
└─ Example: Card reader for different memory cards

Decorator
├─ Add behavior to objects dynamically
└─ Example: Adding toppings to pizza

Facade
├─ Provide simplified interface to complex system
└─ Example: One remote for entire home theater

Composite
├─ Treat individual objects and groups uniformly
└─ Example: File system (files and folders)

Proxy
├─ Provide surrogate or placeholder
└─ Example: Virtual proxy for large images

Bridge
├─ Separate abstraction from implementation
└─ Example: Remote control works with any device

Flyweight
├─ Share common state between objects
└─ Example: Character formatting in text editor
```

### 3. Behavioral Patterns

**Purpose**: Define how objects communicate and collaborate

**Problem They Solve**: How to assign responsibilities between objects

**Focus**: Communication and interaction

**Common Patterns**:
```javascript
Strategy
├─ Define family of algorithms, make them interchangeable
└─ Example: Different payment methods

Observer
├─ Notify multiple objects when state changes
└─ Example: Newsletter subscriptions

Command
├─ Encapsulate request as an object
└─ Example: Undo/Redo functionality

State
├─ Change behavior when internal state changes
└─ Example: Traffic light states

Template Method
├─ Define skeleton, let subclasses fill details
└─ Example: Cooking recipe with variations

Chain of Responsibility
├─ Pass request along chain of handlers
└─ Example: Customer support escalation

Iterator
├─ Access elements sequentially without exposing structure
└─ Example: Playlist navigation

Visitor
├─ Add operations to objects without modifying them
└─ Example: Tax calculation on different items

Mediator
├─ Reduce direct communication between objects
└─ Example: Air traffic control tower

Memento
├─ Save and restore object state
└─ Example: Game save points
```sql

## What Design Patterns Are NOT

**Not Code**: Patterns are concepts, not ready-to-use code

**Not Libraries**: Not pre-written code you can import

**Not Algorithms**: Not step-by-step procedures

**Not Rigid Rules**: Guidelines that can be adapted

## Benefits of Using Design Patterns
```text
┌────────────────────────────────────────────────────┐
│         Benefits of Design Patterns                 │
└────────────────────────────────────────────────────┘

Reusability
└─ Proven solutions you can use repeatedly

Communication
└─ Common vocabulary among developers

Documentation
└─ Self-documenting code structure

Flexibility
└─ Easier to modify and extend

Quality
└─ Avoid common pitfalls

Learning
└─ Learn from expert experiences
```

## When to Use Design Patterns

**Use Patterns When**:
- Problem matches pattern's intent
- Solution would benefit from proven approach
- Team understands the pattern
- Flexibility and extensibility are needed

**Don't Use Patterns When**:
- Simple solution works better
- Pattern adds unnecessary complexity
- Team isn't familiar with pattern
- Problem doesn't match pattern's use case

## Common Misconceptions
```text
❌ Misconception: Use patterns everywhere
✅ Reality: Use patterns when they add value

❌ Misconception: Patterns are always the best solution
✅ Reality: Simple code is often better than complex patterns

❌ Misconception: Must follow patterns exactly
✅ Reality: Adapt patterns to your needs

❌ Misconception: More patterns = better code
✅ Reality: Right pattern at right place = better code
```

## How to Learn Design Patterns

### 1. Understand the Problem

Before learning a pattern, understand what problem it solves.

### 2. See Examples

Look at real-world examples and code implementations.

### 3. Practice

Implement patterns in small projects.

### 4. Recognize Opportunities

Learn to identify when a pattern would help.

### 5. Start Simple

Begin with commonly used patterns like Singleton, Factory, Strategy.

## Pattern Selection Guide
```text
┌────────────────────────────────────────────────────┐
│        When to Use Which Pattern?                   │
└────────────────────────────────────────────────────┘

Need to control object creation?
└─> Creational Patterns (Singleton, Factory, Builder)

Need to organize object relationships?
└─> Structural Patterns (Adapter, Decorator, Facade)

Need to manage object communication?
└─> Behavioral Patterns (Strategy, Observer, Command)
```text

## Pattern Relationships

Patterns often work together:
```text
Builder Pattern
    ↓ (can use)
Factory Pattern
    ↓ (may create)
Singleton Pattern
    ↓ (combined with)
Observer Pattern
```

**Example**: A Singleton Logger might use Factory to create different log handlers, which are Observers of log events.

## Real-World Analogy

Think of design patterns like **cooking recipes**:
```text
Recipe (Pattern)          Cooking (Implementation)
├─ Ingredients list       ├─ Classes and interfaces
├─ Step-by-step guide    ├─ Code structure
├─ Expected outcome      ├─ Working solution
└─ Variations possible   └─ Adaptations allowed
```text

Just as recipes:
- Don't force you to cook exactly the same way
- Provide guidelines, not rigid rules
- Can be adapted to available ingredients
- Make cooking easier with proven methods

Design patterns:
- Don't force exact implementation
- Provide structure, not rigid code
- Can be adapted to your situation
- Make development easier with proven approaches

## The Pattern Format

Most patterns are documented with:
```
Pattern Name
├─ Intent: What problem does it solve?
├─ Motivation: Why is it needed?
├─ Applicability: When should you use it?
├─ Structure: Diagram showing classes/objects
├─ Participants: Classes/objects involved
├─ Collaborations: How participants work together
├─ Consequences: Benefits and trade-offs
├─ Implementation: Code examples
└─ Related Patterns: Similar or complementary patterns
```javascript

## Anti-Patterns

**Anti-Pattern**: Common but ineffective solution to a problem

Examples:
```javascript
God Object
└─ One class does everything (violates SRP)

Spaghetti Code
└─ No structure, everything tangled

Copy-Paste Programming
└─ Duplicate code everywhere (violates DRY)

Golden Hammer
└─ Using same solution for every problem
```

**Important**: Knowing what NOT to do is as valuable as knowing design patterns.

## Pattern Evolution

Patterns evolve with:
- New programming languages
- New technologies
- New architectural styles
- Lessons learned from usage

Modern patterns include:
- Dependency Injection
- Repository Pattern
- MVC (Model-View-Controller)
- MVVM (Model-View-ViewModel)

## Getting Started with Patterns

### Step 1: Learn the Basics
Start with the most common patterns:
- Singleton
- Factory
- Strategy
- Observer

### Step 2: Understand When to Use Them
Don't just learn implementation—understand the problem each solves.

### Step 3: Practice
Build small projects using patterns.

### Step 4: Refactor
Apply patterns to existing code when appropriate.

### Step 5: Share Knowledge
Discuss patterns with your team.

## Key Principles Behind Patterns

Most design patterns follow these principles:

**Program to Interface, Not Implementation**
```text
Instead of: PayPalPayment payment = new PayPalPayment();
Use: PaymentMethod payment = new PayPalPayment();
```javascript

**Favor Composition Over Inheritance**
```javascript
Instead of: class Car extends Engine
Use: class Car { private Engine engine; }
```

**Encapsulate What Varies**
```text
Isolate parts that change from parts that stay the same
```text

**Depend on Abstractions, Not Concretions**
```text
High-level modules shouldn't depend on low-level modules
```

## Summary
```javascript
┌────────────────────────────────────────────────────┐
│        Design Patterns Quick Reference              │
└────────────────────────────────────────────────────┘

What are they?
└─ Reusable solutions to common problems

Three Categories:
├─ Creational: Object creation
├─ Structural: Object composition
└─ Behavioral: Object communication

Benefits:
├─ Proven solutions
├─ Common vocabulary
├─ Faster development
└─ Better maintainability

When to use:
├─ Problem matches pattern
├─ Adds real value
└─ Team understands it

When NOT to use:
├─ Adds unnecessary complexity
├─ Simple solution exists
└─ Doesn't fit the problem
```javascript

## What's Next?

In the following chapters, we'll explore each pattern in detail:

1. **Creational Patterns**: Learn how to create objects elegantly
2. **Structural Patterns**: Learn how to compose objects effectively
3. **Behavioral Patterns**: Learn how to manage object interactions
4. **Additional Patterns**: Modern patterns for specific scenarios

Each pattern will include:
- Problem it solves
- When to use it
- Structure and participants
- Code examples
- Real-world scenarios
- Benefits and trade-offs

Remember: **Design patterns are tools in your toolbox**. The key is knowing which tool to use for which job, and sometimes the best tool is no pattern at all—just simple, clean code.

---
# Singleton Pattern

The Singleton pattern ensures that a class has only one instance throughout the application and provides a global point of access to that instance.

## What is Singleton Pattern?

**Singleton Pattern**: Restricts a class to have exactly one instance and provides global access to it.

**Core Idea**: One instance for the entire application

Think of a **country's president**:
- Only one president at a time
- Everyone knows who the president is
- Single point of authority

## Problem It Solves

**Without Singleton**:
```javascript
const db1 = new Database();
const db2 = new Database();
const db3 = new Database();

// Problem: Multiple database connections created
// Wastes resources, causes inconsistencies
```javascript

**With Singleton**:
```javascript
const db1 = Database.getInstance();
const db2 = Database.getInstance();
const db3 = Database.getInstance();

// db1, db2, db3 all reference the same instance
// Single connection, consistent state
```

## When to Use Singleton

**Use When**:
- Need exactly one instance (database connection, logger)
- Global access point required
- Resource sharing needed (configuration, cache)
- Controlled access to single resource

**Don't Use When**:
- Multiple instances might be needed later
- Testing becomes difficult (hard to mock)
- Creates global state (can cause hidden dependencies)

## Structure
```sql
┌────────────────────────┐
│      Singleton         │
├────────────────────────┤
│ - instance: Singleton  │ ← Single instance
├────────────────────────┤
│ - constructor()        │ ← Private constructor
│ + getInstance()        │ ← Public access method
└────────────────────────┘
```javascript

## Basic Implementation
```javascript
class Database {
    static #instance = null;  // Private static instance
    
    // Private constructor - prevents direct instantiation
    constructor() {
        if (Database.#instance) {
            throw new Error("Use Database.getInstance()");
        }
        
        this.connection = "Database connection established";
        Database.#instance = this;
    }
    
    // Public method to get instance
    static getInstance() {
        if (!Database.#instance) {
            Database.#instance = new Database();
        }
        return Database.#instance;
    }
    
    query(sql) {
        console.log(`Executing: ${sql}`);
    }
}

// Usage
const db1 = Database.getInstance();
const db2 = Database.getInstance();
const db3 = Database.getInstance();

console.log(db1 === db2);  // true
console.log(db2 === db3);  // true

// All reference the same instance
db1.query("SELECT * FROM users");
```javascript

## Real-World Examples

### 1. Logger
```javascript
class Logger {
    static #instance = null;
    #logs = [];
    
    constructor() {
        if (Logger.#instance) {
            return Logger.#instance;
        }
        Logger.#instance = this;
    }
    
    static getInstance() {
        if (!Logger.#instance) {
            Logger.#instance = new Logger();
        }
        return Logger.#instance;
    }
    
    log(message) {
        const timestamp = new Date().toISOString();
        this.#logs.push(`[${timestamp}] ${message}`);
        console.log(`[${timestamp}] ${message}`);
    }
    
    getLogs() {
        return this.#logs;
    }
}

// Usage across application
const logger1 = Logger.getInstance();
logger1.log("User logged in");

const logger2 = Logger.getInstance();
logger2.log("Order placed");

console.log(logger1 === logger2);  // true
console.log(logger1.getLogs());    // Both logs present
```javascript

### 2. Configuration Manager
```javascript
class ConfigManager {
    static #instance = null;
    #config = {};
    
    constructor() {
        if (ConfigManager.#instance) {
            return ConfigManager.#instance;
        }
        
        // Load configuration
        this.#config = {
            apiUrl: "https://api.example.com",
            timeout: 5000,
            retries: 3
        };
        
        ConfigManager.#instance = this;
    }
    
    static getInstance() {
        if (!ConfigManager.#instance) {
            ConfigManager.#instance = new ConfigManager();
        }
        return ConfigManager.#instance;
    }
    
    get(key) {
        return this.#config[key];
    }
    
    set(key, value) {
        this.#config[key] = value;
    }
}

// Usage
const config1 = ConfigManager.getInstance();
console.log(config1.get("apiUrl"));

const config2 = ConfigManager.getInstance();
config2.set("timeout", 10000);

console.log(config1.get("timeout"));  // 10000
// Both share same configuration
```

### 3. Application State
```javascript
class AppState {
    static #instance = null;
    #state = {};
    
    constructor() {
        if (AppState.#instance) {
            return AppState.#instance;
        }
        
        this.#state = {
            user: null,
            theme: "light",
            language: "en"
        };
        
        AppState.#instance = this;
    }
    
    static getInstance() {
        if (!AppState.#instance) {
            AppState.#instance = new AppState();
        }
        return AppState.#instance;
    }
    
    getState() {
        return { ...this.#state };
    }
    
    setState(key, value) {
        this.#state[key] = value;
    }
}

// Usage
const state = AppState.getInstance();
state.setState("user", { name: "Alice", id: 1 });

// Elsewhere in application
const appState = AppState.getInstance();
console.log(appState.getState().user);  // { name: "Alice", id: 1 }
```text

## Key Components
```sql
┌────────────────────────────────────────────────────┐
│         Singleton Pattern Components                │
└────────────────────────────────────────────────────┘

Private Constructor
└─ Prevents direct instantiation with 'new'

Static Instance Variable
└─ Holds the single instance

Static getInstance() Method
└─ Creates instance on first call
└─ Returns existing instance on subsequent calls

Instance Methods
└─ Provide functionality
```javascript

## Benefits

**Single Instance**: Only one object exists in memory

**Global Access**: Accessible from anywhere in application

**Lazy Initialization**: Created only when first needed

**Resource Control**: Manages shared resources efficiently

**Consistent State**: Same data across entire application

## Drawbacks

**Global State**: Can create hidden dependencies

**Testing Difficulty**: Hard to mock or replace in tests

**Hidden Dependencies**: Classes depend on singleton without explicit declaration

**Violates Single Responsibility**: Manages its own lifecycle and business logic

**Thread Safety**: May need special handling in multithreaded environments

## Common Mistakes

### Mistake 1: Not Making Constructor Private
```javascript
// Bad - Constructor is public
class Singleton {
    static instance = null;
    
    constructor() {
        // Anyone can call 'new Singleton()'
    }
}

const s1 = new Singleton();  // Creates new instance
const s2 = new Singleton();  // Creates another instance
// Multiple instances created!
```javascript

### Mistake 2: Not Checking Existing Instance
```javascript
// Bad - Always creates new instance
class Singleton {
    static getInstance() {
        return new Singleton();  // Wrong! Creates new each time
    }
}
```javascript

### Mistake 3: Mutable Shared State
```javascript
// Bad - Direct access to mutable state
class Singleton {
    static #instance = null;
    state = {};  // Public mutable state
    
    static getInstance() {
        if (!Singleton.#instance) {
            Singleton.#instance = new Singleton();
        }
        return Singleton.#instance;
    }
}

// Problem: Anyone can modify state directly
const s = Singleton.getInstance();
s.state = null;  // Breaks the singleton
```

## Alternatives to Singleton

### 1. Dependency Injection
```javascript
// Instead of Singleton
class Logger {
    log(message) {
        console.log(message);
    }
}

// Inject logger where needed
class UserService {
    constructor(logger) {
        this.logger = logger;
    }
    
    createUser(user) {
        this.logger.log("User created");
    }
}

// Create once, inject everywhere
const logger = new Logger();
const userService = new UserService(logger);
```javascript

### 2. Module Pattern
```javascript
// Single instance through module
const database = {
    connection: "Connected",
    query(sql) {
        console.log(`Query: ${sql}`);
    }
};

export default database;

// Import and use
import database from './database.js';
database.query("SELECT * FROM users");
```javascript

## Testing Challenges

**Problem**: Hard to reset singleton between tests

**Solution 1 - Reset Method**:
```javascript
class Singleton {
    static #instance = null;
    
    static getInstance() {
        if (!Singleton.#instance) {
            Singleton.#instance = new Singleton();
        }
        return Singleton.#instance;
    }
    
    // For testing only
    static resetInstance() {
        Singleton.#instance = null;
    }
}

// In tests
afterEach(() => {
    Singleton.resetInstance();
});
```javascript

**Solution 2 - Dependency Injection**:
```javascript
// Better: Use DI instead of Singleton
class Service {
    constructor(dependency) {
        this.dependency = dependency;
    }
}

// Easy to test with mocks
const mockDep = { method: () => "mocked" };
const service = new Service(mockDep);
```sql

## Real-World Use Cases
```text
┌────────────────────────────────────────────────────┐
│         Common Singleton Applications               │
└────────────────────────────────────────────────────┘

Database Connection Pool
└─ Single pool manages all connections

Logger
└─ Centralized logging throughout app

Configuration Manager
└─ Single source of app settings

Cache Manager
└─ Shared cache for entire application

Thread Pool
└─ Manages fixed number of threads

Device Manager
└─ Controls hardware resources
```javascript

## Best Practices

**Lazy Initialization**: Create instance only when needed

**Thread Safety**: Consider concurrent access if needed

**Private Constructor**: Prevent direct instantiation

**Immutable State**: Make shared state read-only when possible

**Clear Purpose**: Use only when truly need single instance

**Document Usage**: Make it clear class is singleton

## Key Takeaways

- **Ensures one instance** exists throughout application
- **Global access point** to that instance
- **Use sparingly** - can create tight coupling
- **Good for**: Database connections, loggers, configuration
- **Bad for**: Everything else (use dependency injection)
- **Consider alternatives** before using singleton

**Remember**: Just because you CAN make something a singleton doesn't mean you SHOULD. Use it only when you truly need exactly one instance.

---

# Builder Pattern

The Builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

## What is Builder Pattern?

**Builder Pattern**: Constructs complex objects step by step, allowing different configurations of the same object type.

**Core Idea**: Build complex objects piece by piece

Think of **ordering a custom burger**:
- Choose bun type
- Add patty
- Select cheese
- Add toppings
- Choose sauce
- Same process, different burgers

## Problem It Solves

**Without Builder**:
```javascript
// Telescoping constructor - confusing and error-prone
const burger = new Burger(
    "sesame",     // bun
    "beef",       // patty
    "cheddar",    // cheese
    true,         // lettuce
    false,        // tomato
    true,         // onion
    "mayo"        // sauce
);

// What does 'true, false, true' mean?
// Easy to mix up the order
```javascript

**With Builder**:
```javascript
const burger = new BurgerBuilder()
    .setBun("sesame")
    .setPatty("beef")
    .setCheese("cheddar")
    .addLettuce()
    .addOnion()
    .setSauce("mayo")
    .build();

// Clear, readable, flexible
```

## When to Use Builder

**Use When**:
- Object has many parameters (4+)
- Many parameters are optional
- Construction process is complex
- Need different representations of same object
- Want immutable objects

**Don't Use When**:
- Object is simple (few parameters)
- All parameters are required
- No variations needed
- Simple constructor works fine

## Structure
```text
┌────────────────────────┐
│       Builder          │
├────────────────────────┤
│ + setPartA()           │
│ + setPartB()           │
│ + setPartC()           │
│ + build()              │
└────────────────────────┘
          │
          │ creates
          ▼
┌────────────────────────┐
│      Product           │
├────────────────────────┤
│ - partA                │
│ - partB                │
│ - partC                │
└────────────────────────┘
```text

## Key Components
```javascript
┌────────────────────────────────────────────────────┐
│         Builder Pattern Components                  │
└────────────────────────────────────────────────────┘

Builder
└─ Provides methods to set each part

Product
└─ Complex object being built

Director (Optional)
└─ Defines order of construction steps

build()
└─ Returns final constructed object
```text

## Real-World Examples

### 1. Database Query Builder
```
Build complex SQL queries step by step:

query
    .select("name", "email")
    .from("users")
    .where("age > 18")
    .orderBy("name")
    .limit(10)
    .build()

Result: "SELECT name, email FROM users WHERE age > 18 ORDER BY name LIMIT 10"
```text

### 2. HTML Document Builder
```
Build HTML documents:

html
    .addHead()
        .setTitle("My Page")
        .addStylesheet("style.css")
    .addBody()
        .addHeader("Welcome")
        .addParagraph("Content here")
        .addButton("Click Me")
    .build()
```text

### 3. Email Builder
```
Compose emails:

email
    .setFrom("sender@example.com")
    .setTo("receiver@example.com")
    .setSubject("Hello")
    .setBody("Message content")
    .addAttachment("file.pdf")
    .setPriority("high")
    .build()
```text

### 4. Report Generator
```text
Generate reports with different sections:

report
    .setTitle("Sales Report")
    .addSummary(data)
    .addChart("revenue", revenueData)
    .addTable("top_products", products)
    .setFormat("PDF")
    .build()
```

## Builder vs Constructor
```text
┌────────────────────────────────────────────────────┐
│        Constructor vs Builder Pattern               │
└────────────────────────────────────────────────────┘

Constructor                    Builder
├─ All at once                ├─ Step by step
├─ Fixed order                ├─ Flexible order
├─ Hard to read (many params) ├─ Clear, readable
├─ Required params unclear    ├─ Optional params clear
└─ Can't skip optional params └─ Skip any optional params
```javascript

## Benefits

**Readability**: Clear what each parameter means

**Flexibility**: Set only needed parameters

**Immutability**: Can create immutable objects

**Control**: Step-by-step construction control

**Reusability**: Reuse builder for different configurations

**Validation**: Validate in build() method before creating object

## Drawbacks

**More Code**: Requires additional builder class

**Complexity**: Overkill for simple objects

**Memory**: Creates intermediate builder object

**Learning Curve**: Team needs to understand pattern

## Method Chaining (Fluent Interface)

Builder pattern often uses method chaining:
```javascript
Return 'this' from each method:

setBun(type) {
    this.bun = type;
    return this;  // Return builder for chaining
}

Allows chaining:
builder.setBun("wheat").setPatty("beef").setCheese("swiss")
```javascript

## Common Variations

### 1. Simple Builder

Just the builder class and product.

### 2. Director

Separate class that knows construction steps:
```text
Director defines recipes:
- makeCheeseBurger()
- makeVeggieBurger()
- makeDoubleBurger()

Each uses builder in specific way
```

### 3. Fluent Builder

Emphasizes readable, sentence-like code:
```text
car
    .withEngine("V8")
    .withColor("red")
    .withSunroof()
    .build()
```text

## Validation in Builder

**Where to Validate**:
```text
Option 1: In build()
└─ Validate all at once before creating object

Option 2: In each setter
└─ Validate as you go

Option 3: Both
└─ Basic validation in setters, final check in build()
```

## Builder with Required Parameters

Handle required parameters:
```javascript
Option 1: Constructor takes required params
new UserBuilder(requiredId, requiredName)
    .setEmail("email@example.com")
    .build()

Option 2: Separate builder creation
UserBuilder.withRequired(id, name)
    .setEmail("email@example.com")
    .build()

Option 3: Validate in build()
builder.build() throws error if required fields missing
```text

## Real-World Use Cases
```text
┌────────────────────────────────────────────────────┐
│         Common Builder Applications                 │
└────────────────────────────────────────────────────┘

Complex Object Creation
└─ Objects with many optional parameters

Test Data
└─ Create test objects with specific configurations

Configuration
└─ Application settings with many options

Document Generation
└─ HTML, XML, JSON documents

Query Construction
└─ SQL, API queries

Request Building
└─ HTTP requests, API calls

UI Components
└─ Complex UI with many customizations
```javascript

## Builder vs Factory
```text
┌────────────────────────────────────────────────────┐
│           Builder vs Factory Pattern                │
└────────────────────────────────────────────────────┘

Builder                        Factory
├─ Constructs step by step     ├─ Creates in one step
├─ Focus on how to build       ├─ Focus on what to create
├─ Many optional parameters    ├─ Few parameters
├─ Multiple configurations     ├─ Different types/classes
└─ Same class, different setup └─ Different classes
```javascript

## Best Practices

**Clear Naming**: Use descriptive method names (setBun, addLettuce)

**Immutability**: Make final product immutable

**Validation**: Validate in build() method

**Required Fields**: Handle required parameters explicitly

**Return This**: Enable method chaining with `return this`

**Separate Concerns**: Builder builds, product has business logic

**Documentation**: Document required vs optional fields

## Pros and Cons Summary
```javascript
✅ Pros
├─ Clean, readable code
├─ Flexible object creation
├─ Handles optional parameters well
├─ Immutable objects possible
└─ Step-by-step construction control

❌ Cons
├─ More code to write
├─ Overkill for simple objects
├─ Additional class to maintain
└─ Slightly more memory usage
```

## Key Takeaways

- **Constructs complex objects** step by step
- **Separates construction** from representation
- **Makes code readable** with method chaining
- **Handles optional parameters** elegantly
- **Use when**: Many parameters, especially optional ones
- **Don't use when**: Object is simple and straightforward

**Remember**: Builder pattern is about making complex object creation simple and readable. If your object isn't complex, you probably don't need a builder.

---

# Factory Method Pattern

The Factory Method pattern defines an interface for creating objects but lets subclasses decide which class to instantiate. It delegates object creation to subclasses.

## What is Factory Method Pattern?

**Factory Method Pattern**: Provides an interface for creating objects without specifying their exact classes.

**Core Idea**: Let subclasses decide which object to create

Think of a **logistics company**:
- RoadLogistics creates Truck
- SeaLogistics creates Ship
- AirLogistics creates Plane
- Each decides what vehicle to create

## Problem It Solves

**Without Factory Method**:
```javascript
Creating objects directly everywhere:

if (type === "truck") {
    vehicle = new Truck();
} else if (type === "ship") {
    vehicle = new Ship();
} else if (type === "plane") {
    vehicle = new Plane();
}

// Repeated in many places
// Hard to add new types
// Tight coupling
```javascript

**With Factory Method**:
```javascript
Each logistics type creates its own vehicle:

RoadLogistics → creates Truck
SeaLogistics → creates Ship
AirLogistics → creates Plane

// Easy to add new types
// No if-else chains
// Loose coupling
```text

## When to Use Factory Method

**Use When**:
- Don't know exact types beforehand
- Want to delegate creation to subclasses
- Need to extend object creation
- Want to avoid tight coupling
- Multiple related classes need creation

**Don't Use When**:
- Simple object creation is sufficient
- No variations in object types
- Only one type of object
- Adds unnecessary complexity

## Structure
```text
┌──────────────────┐
│    Creator       │ (Abstract)
├──────────────────┤
│ + factoryMethod()│ ← Abstract method
│ + operation()    │
└────────△─────────┘
         │
    ┌────┴────┐
    │         │
┌───┴──────┐ ┌┴──────────┐
│ConcreteA │ │ConcreteB  │
├──────────┤ ├───────────┤
│+factory()│ │+factory() │
└────┬─────┘ └─────┬─────┘
     │             │
  creates       creates
     │             │
     ▼             ▼
┌─────────┐   ┌─────────┐
│ProductA │   │ProductB │
└─────────┘   └─────────┘
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│      Factory Method Pattern Components              │
└────────────────────────────────────────────────────┘

Creator (Abstract)
└─ Declares factory method that returns Product

Concrete Creators
└─ Override factory method to create specific products

Product Interface
└─ Defines interface for objects factory creates

Concrete Products
└─ Implement Product interface
```

## Real-World Examples

### 1. Document Editor
```text
DocumentCreator
├─ WordCreator → creates WordDocument
├─ PDFCreator → creates PDFDocument
└─ ExcelCreator → creates ExcelDocument

Each creator knows how to create its document type
User doesn't need to know details
```text

### 2. Payment Processing
```text
PaymentFactory
├─ CreditCardFactory → creates CreditCardProcessor
├─ PayPalFactory → creates PayPalProcessor
└─ CryptoFactory → creates CryptoProcessor

Based on payment method, appropriate processor is created
```

### 3. UI Components
```text
DialogFactory
├─ WindowsDialog → creates WindowsButton, WindowsCheckbox
├─ MacDialog → creates MacButton, MacCheckbox
└─ LinuxDialog → creates LinuxButton, LinuxCheckbox

Each OS has its own look and feel
Factory creates appropriate components
```text

### 4. Notification System
```text
NotificationFactory
├─ EmailNotificationFactory → creates EmailNotification
├─ SMSNotificationFactory → creates SMSNotification
└─ PushNotificationFactory → creates PushNotification

Based on user preference, creates right notification type
```

## How It Works
```javascript
┌────────────────────────────────────────────────────┐
│            Factory Method Flow                      │
└────────────────────────────────────────────────────┘

Step 1: Client needs a product
    ↓
Step 2: Calls factory method on creator
    ↓
Step 3: Creator's subclass creates specific product
    ↓
Step 4: Returns product through common interface
    ↓
Step 5: Client uses product without knowing its type
```javascript

## Benefits

**Loose Coupling**: Code depends on interfaces, not concrete classes

**Single Responsibility**: Object creation separated from usage

**Open/Closed Principle**: Easy to add new products without changing existing code

**Flexibility**: Subclasses decide what to create

**Reusability**: Common creation logic in base class

## Drawbacks

**Complexity**: More classes to manage

**Indirect**: Extra level of abstraction

**Overkill**: Too complex for simple scenarios

**Learning Curve**: Harder for beginners to understand

## Factory Method vs Simple Factory
```javascript
┌────────────────────────────────────────────────────┐
│      Factory Method vs Simple Factory               │
└────────────────────────────────────────────────────┘

Simple Factory              Factory Method
├─ One factory class        ├─ Multiple factory subclasses
├─ Uses if-else/switch      ├─ Uses inheritance
├─ Not a design pattern     ├─ True design pattern
├─ Limited extensibility    ├─ Easily extensible
└─ Simple to implement      └─ More structured
```text

## Factory Method vs Abstract Factory
```text
┌────────────────────────────────────────────────────┐
│    Factory Method vs Abstract Factory               │
└────────────────────────────────────────────────────┘

Factory Method              Abstract Factory
├─ Creates one product      ├─ Creates families of products
├─ Uses inheritance         ├─ Uses composition
├─ Single method            ├─ Multiple methods
└─ One product type         └─ Related products together
```text

## Variations

### 1. Parameterized Factory Method
```
Takes parameter to decide which product to create:
createVehicle(type)

Returns different products based on parameter
```javascript

### 2. Creator Uses Factory Method
```javascript
Base class calls factory method internally:
operation() {
    product = factoryMethod();
    product.doSomething();
}

Template Method pattern combined with Factory Method
```javascript

### 3. Default Implementation
```javascript
Base class provides default factory method:
factoryMethod() {
    return new DefaultProduct();
}

Subclasses can override if needed
```text

## Real-World Scenarios
```text
┌────────────────────────────────────────────────────┐
│       Common Factory Method Applications           │
└────────────────────────────────────────────────────┘

Database Connections
└─ MySQL, PostgreSQL, MongoDB connections

File Parsers
└─ JSON, XML, CSV parsers

Authentication Methods
└─ OAuth, JWT, SAML authenticators

Rendering Engines
└─ 2D, 3D, Canvas renderers

Logging Systems
└─ File, Console, Remote loggers

Transport Layers
└─ HTTP, WebSocket, gRPC transports
```

## Design Principles Applied

**Dependency Inversion**: Depend on abstractions, not concretions

**Open/Closed**: Open for extension (new factories), closed for modification

**Single Responsibility**: Creation separated from business logic

**Polymorphism**: Different implementations through common interface

## Common Use Cases

### When You See These, Consider Factory Method:

**"Based on type, create..."**
```text
Based on document type, create appropriate editor
Based on payment method, create processor
Based on platform, create UI components
```text

**"Need to extend with new types..."**
```javascript
Easy to add new document types
Easy to add new payment methods
Easy to add new platforms
```text

**"Multiple implementations of..."**
```
Multiple database drivers
Multiple file formats
Multiple authentication methods
```text

## Best Practices

**Return Interface**: Factory method should return interface, not concrete class

**Meaningful Names**: Use descriptive names (createDocument, not create)

**Single Responsibility**: Factory only creates, doesn't configure

**Avoid Logic**: Keep factory method simple, delegate complexity

**Consider Alternatives**: Sometimes simple constructor is better

**Document Intent**: Make clear what each factory creates

## Pros and Cons Summary
```
✅ Pros
├─ Loose coupling
├─ Single Responsibility Principle
├─ Open/Closed Principle
├─ Easy to extend
└─ Flexible and reusable

❌ Cons
├─ More classes
├─ Increased complexity
├─ Indirect creation
└─ Steeper learning curve
```javascript

## When NOT to Use

**Simple Object Creation**: Just use constructor

**Only One Type**: No variations needed

**No Future Extensions**: Won't add new types

**Team Unfamiliar**: Simpler patterns work better

**Over-Engineering**: Adds complexity without benefit

## Key Takeaways

- **Delegates object creation** to subclasses
- **Each subclass** decides what to create
- **Client code** works with interface, not concrete classes
- **Easy to extend** with new product types
- **Use when**: Multiple related types, need flexibility
- **Don't use when**: Simple creation is sufficient

**Remember**: Factory Method is about delegating the responsibility of instantiation. If you're not delegating or extending, you might not need it.

---
# Abstract Factory Pattern

The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

## What is Abstract Factory Pattern?

**Abstract Factory Pattern**: Creates families of related objects without specifying their concrete classes.

**Core Idea**: Factory of factories - creates groups of related objects

Think of a **furniture store**:
- Modern furniture set: Modern chair, modern table, modern sofa
- Victorian furniture set: Victorian chair, Victorian table, Victorian sofa
- Art Deco furniture set: Art Deco chair, Art Deco table, Art Deco sofa
- Each set has matching style across all pieces

## Problem It Solves

**Without Abstract Factory**:
```javascript
Creating UI components for different platforms:

// Problem: Easy to mix incompatible components
button = new WindowsButton();
checkbox = new MacCheckbox();    // Mismatch!
scrollbar = new LinuxScrollbar(); // Inconsistent!

// Result: Inconsistent UI
```sql

**With Abstract Factory**:
```javascript
Use factory for entire family:

windowsFactory → WindowsButton + WindowsCheckbox + WindowsScrollbar
macFactory → MacButton + MacCheckbox + MacScrollbar
linuxFactory → LinuxButton + LinuxCheckbox + LinuxScrollbar

// All components match the platform
```text

## When to Use Abstract Factory

**Use When**:
- System needs families of related products
- Products must be used together
- Want to enforce consistency across product families
- Need to switch entire product families
- Hide concrete implementations from client

**Don't Use When**:
- Only single products needed (use Factory Method)
- Product families don't need consistency
- Adds unnecessary complexity
- Only one family exists

## Structure
```text
┌──────────────────────┐
│  AbstractFactory     │
├──────────────────────┤
│ +createProductA()    │
│ +createProductB()    │
└──────────△───────────┘
           │
      ┌────┴────┐
      │         │
┌─────┴──────┐ ┌┴────────────┐
│ConcreteF1  │ │ConcreteF2   │
├────────────┤ ├─────────────┤
│+createA()  │ │+createA()   │
│+createB()  │ │+createB()   │
└──────┬─────┘ └──────┬──────┘
       │              │
    creates        creates
       │              │
   ┌───┴──┐       ┌───┴──┐
   │      │       │      │
   ▼      ▼       ▼      ▼
ProductA1 ProductB1 ProductA2 ProductB2
```

## Key Components
```text
┌────────────────────────────────────────────────────┐
│    Abstract Factory Pattern Components              │
└────────────────────────────────────────────────────┘

Abstract Factory
└─ Interface for creating family of products

Concrete Factories
└─ Implement creation methods for specific family

Abstract Products
└─ Interfaces for each type of product

Concrete Products
└─ Actual products created by concrete factories

Client
└─ Uses abstract factory and product interfaces
```text

## Real-World Examples

### 1. Cross-Platform UI Components
```javascript
UIFactory (Abstract)
├─ createButton()
├─ createCheckbox()
└─ createScrollbar()

WindowsUIFactory
├─ creates WindowsButton
├─ creates WindowsCheckbox
└─ creates WindowsScrollbar

MacUIFactory
├─ creates MacButton
├─ creates MacCheckbox
└─ creates MacScrollbar

LinuxUIFactory
├─ creates LinuxButton
├─ creates LinuxCheckbox
└─ creates LinuxScrollbar

// All components match the platform style
```

### 2. Furniture Shop
```javascript
FurnitureFactory (Abstract)
├─ createChair()
├─ createTable()
└─ createSofa()

ModernFurnitureFactory
├─ creates ModernChair
├─ creates ModernTable
└─ creates ModernSofa

VictorianFurnitureFactory
├─ creates VictorianChair
├─ creates VictorianTable
└─ creates VictorianSofa

ArtDecoFurnitureFactory
├─ creates ArtDecoChair
├─ creates ArtDecoTable
└─ creates ArtDecoSofa

// All furniture pieces match the style
```text

### 3. Database Connection Factory
```javascript
DatabaseFactory (Abstract)
├─ createConnection()
├─ createCommand()
└─ createDataReader()

MySQLFactory
├─ creates MySQLConnection
├─ creates MySQLCommand
└─ creates MySQLDataReader

PostgreSQLFactory
├─ creates PostgreSQLConnection
├─ creates PostgreSQLCommand
└─ creates PostgreSQLDataReader

MongoDBFactory
├─ creates MongoDBConnection
├─ creates MongoDBCommand
└─ creates MongoDBDataReader

// All components work together for same database
```

### 4. Document Generator
```javascript
DocumentFactory (Abstract)
├─ createHeader()
├─ createBody()
└─ createFooter()

PDFDocumentFactory
├─ creates PDFHeader
├─ creates PDFBody
└─ creates PDFFooter

WordDocumentFactory
├─ creates WordHeader
├─ creates WordBody
└─ creates WordFooter

HTMLDocumentFactory
├─ creates HTMLHeader
├─ creates HTMLBody
└─ creates HTMLFooter

// All parts create consistent document format
```text

## How It Works
```text
┌────────────────────────────────────────────────────┐
│         Abstract Factory Flow                       │
└────────────────────────────────────────────────────┘

Step 1: Client receives factory instance
    ↓
Step 2: Client calls factory methods
    ↓
Step 3: Factory creates family of related products
    ↓
Step 4: All products are compatible with each other
    ↓
Step 5: Client uses products through interfaces
```sql

## Benefits

**Consistency**: Ensures products from same family work together

**Isolation**: Separates concrete classes from client code

**Easy Switching**: Change entire product family by changing factory

**Single Responsibility**: Creation logic in one place

**Open/Closed**: Add new families without modifying existing code

## Drawbacks

**Complexity**: Many classes and interfaces to manage

**Rigidity**: Adding new product types requires changing all factories

**Over-Engineering**: Overkill for simple scenarios

**Learning Curve**: Harder to understand than simpler patterns

## Abstract Factory vs Factory Method
```text
┌────────────────────────────────────────────────────┐
│    Abstract Factory vs Factory Method               │
└────────────────────────────────────────────────────┘

Abstract Factory              Factory Method
├─ Creates families           ├─ Creates single product
├─ Multiple create methods    ├─ One create method
├─ Composition-based          ├─ Inheritance-based
├─ Product families           ├─ Product variations
└─ Ensures compatibility      └─ Flexible creation
```text

**Example**:
- **Factory Method**: VehicleFactory creates different vehicles
- **Abstract Factory**: TransportFactory creates vehicle + driver + fuel compatible set

## Product Families vs Product Types
```
Product Families (Abstract Factory)
└─ Different styles of same products
└─ Example: Modern vs Victorian furniture

Product Types (Factory Method)
└─ Different types of products
└─ Example: Chair vs Table vs Sofa
```text

## Common Scenarios

### Theme-Based Applications
```text
ThemeFactory
├─ LightTheme → Light colors, light icons, light fonts
├─ DarkTheme → Dark colors, dark icons, dark fonts
└─ HighContrastTheme → High contrast everything

All components must match the theme
```text

### Platform-Specific Code
```
PlatformFactory
├─ AndroidFactory → Android-specific components
├─ iOSFactory → iOS-specific components
└─ WebFactory → Web-specific components

All components work together on same platform
```text

### Configuration Sets
```text
ConfigurationFactory
├─ DevelopmentConfig → Dev DB, dev API, dev logger
├─ StagingConfig → Staging DB, staging API, staging logger
└─ ProductionConfig → Prod DB, prod API, prod logger

All configuration components for same environment
```text

## Real-World Use Cases
```text
┌────────────────────────────────────────────────────┐
│     Common Abstract Factory Applications            │
└────────────────────────────────────────────────────┘

Cross-Platform Applications
└─ UI components for different operating systems

Theme Management
└─ Light/Dark/Custom themes with matching components

Database Abstraction
└─ Different database systems with compatible drivers

Document Formats
└─ PDF/Word/HTML with matching formatters

Gaming Environments
└─ Medieval/SciFi/Modern with matching assets

E-commerce Platforms
└─ Different payment gateways with compatible components
```

## Design Principles Applied

**Dependency Inversion**: Client depends on abstractions

**Open/Closed**: Open for new families, closed for modification

**Single Responsibility**: Each factory creates one family

**Interface Segregation**: Clients use only needed factory methods

## Implementing Abstract Factory

### Step 1: Define Product Interfaces
```text
All related products need interfaces:
- Button interface
- Checkbox interface
- Scrollbar interface
```text

### Step 2: Create Concrete Products
```text
Implement products for each family:
- WindowsButton, MacButton
- WindowsCheckbox, MacCheckbox
- WindowsScrollbar, MacScrollbar
```

### Step 3: Define Abstract Factory
```text
Factory interface with creation methods:
- createButton()
- createCheckbox()
- createScrollbar()
```text

### Step 4: Implement Concrete Factories
```text
Each factory creates one complete family:
- WindowsFactory
- MacFactory
```

### Step 5: Client Uses Factory
```text
Client works with factory interface:
- Gets factory instance
- Creates all products through factory
- Uses products through interfaces
```sql

## Common Mistakes

**Mistake 1**: Mixing products from different families
```javascript
❌ Bad:
button = windowsFactory.createButton();
checkbox = macFactory.createCheckbox(); // Inconsistent!

✅ Good:
button = factory.createButton();
checkbox = factory.createCheckbox(); // Same factory
```text

**Mistake 2**: Not using product interfaces
```javascript
❌ Bad:
WindowsButton button = factory.createButton(); // Concrete type

✅ Good:
Button button = factory.createButton(); // Interface
```

**Mistake 3**: Adding products breaks all factories
```javascript
Problem: Need to add new product type
Result: Must modify all concrete factories

Solution: Plan product families carefully upfront
```javascript

## When Abstract Factory Shines

**Multiple Platforms**: iOS, Android, Web applications

**Theme Systems**: Light, dark, custom themes

**Database Support**: MySQL, PostgreSQL, MongoDB

**Document Formats**: Different export formats

**Environment Configs**: Dev, staging, production

## Best Practices

**Plan Families**: Think through all product types upfront

**Use Interfaces**: Both factory and products should be interfaces

**Consistency**: Ensure products in family work together

**Factory Selection**: Let configuration or environment determine factory

**Document Relationships**: Make clear which products belong together

**Keep Families Small**: Don't create huge product families

## Pros and Cons Summary
```sql
✅ Pros
├─ Ensures product compatibility
├─ Isolates concrete classes
├─ Easy to switch families
├─ Consistent products
└─ Open/Closed principle

❌ Cons
├─ Complex with many classes
├─ Rigid - hard to add products
├─ Overkill for simple cases
├─ Steeper learning curve
└─ More code to maintain
```javascript

## Key Takeaways

- **Creates families** of related products
- **Multiple factory methods** for different products
- **Ensures compatibility** within product family
- **Easy to switch** entire family at once
- **Use when**: Related products must work together
- **Don't use when**: Single products or no families needed

**Remember**: Abstract Factory is about creating consistent families of products. If products don't need to be compatible or there's only one product type, simpler patterns might be better.

---

# Prototype Pattern

The Prototype pattern creates new objects by copying existing objects (prototypes) rather than creating them from scratch. It allows you to clone objects without coupling to their specific classes.

## What is Prototype Pattern?

**Prototype Pattern**: Creates new objects by cloning existing objects instead of instantiating new ones.

**Core Idea**: Copy existing objects to create new ones

Think of **cell division**:
- Cells reproduce by copying themselves
- New cell is identical to original
- Faster than building from scratch
- Each copy can be modified independently

## Problem It Solves

**Without Prototype**:
```javascript
Creating complex objects from scratch each time:

// Expensive object creation
config = new Configuration();
config.setDatabase("localhost:3306");
config.setUsername("admin");
config.setPassword("secret");
config.setConnectionPool(50);
config.loadSettings();
config.validateSettings();

// Need another similar? Repeat all steps!
// Time-consuming and error-prone
```

**With Prototype**:
```javascript
Clone existing object:

// Create once
original = new Configuration(/* all settings */);

// Clone when needed
config1 = original.clone();
config2 = original.clone();
config3 = original.clone();

// Fast, easy, consistent
```javascript

## When to Use Prototype

**Use When**:
- Object creation is expensive (database, network, file operations)
- Need many similar objects with slight variations
- Want to avoid complex initialization
- Object construction is complex
- Need to hide creation complexity from client
- Classes to instantiate are specified at runtime

**Don't Use When**:
- Object creation is simple and cheap
- Objects don't share common state
- Cloning is more complex than creating
- Deep vs shallow copy issues arise
- Objects have circular references

## Structure
```javascript
┌──────────────────────┐
│    Prototype         │
├──────────────────────┤
│ + clone()            │ ← Cloning method
└──────────△───────────┘
           │
      ┌────┴────┐
      │         │
┌─────┴──────┐ ┌┴────────────┐
│ConcreteA   │ │ConcreteB    │
├────────────┤ ├─────────────┤
│+ clone()   │ │+ clone()    │
└────────────┘ └─────────────┘

Each concrete class implements its own cloning
```text

## Key Components
```javascript
┌────────────────────────────────────────────────────┐
│        Prototype Pattern Components                 │
└────────────────────────────────────────────────────┘

Prototype Interface
└─ Declares clone() method

Concrete Prototype
└─ Implements clone() to copy itself

Client
└─ Creates new objects by cloning prototypes

Prototype Registry (Optional)
└─ Stores frequently used prototypes
```text

## Cloning Types

### Shallow Copy
```text
┌────────────────────────────────────────────────────┐
│              Shallow Copy                           │
└────────────────────────────────────────────────────┘

Original Object          Cloned Object
├─ primitive: 42    →   ├─ primitive: 42 (copied)
├─ string: "text"   →   ├─ string: "text" (copied)
└─ reference: obj   →   └─ reference: obj (same reference!)

Problem: Both share the same referenced object
Changing nested object affects both copies
```

### Deep Copy
```javascript
┌────────────────────────────────────────────────────┐
│               Deep Copy                             │
└────────────────────────────────────────────────────┘

Original Object          Cloned Object
├─ primitive: 42    →   ├─ primitive: 42 (copied)
├─ string: "text"   →   ├─ string: "text" (copied)
└─ reference: obj1  →   └─ reference: obj2 (new copy!)

Solution: Nested objects are also cloned
Each copy is completely independent
```text

## Real-World Examples

### 1. Document Templates
```sql
DocumentPrototype
├─ BlankDocument (basic template)
├─ ResumeTemplate (pre-formatted resume)
├─ ReportTemplate (company report format)
└─ InvoiceTemplate (invoice format)

Clone template → Customize for specific use
Faster than creating from scratch each time
```text

### 2. Game Characters
```
CharacterPrototype
├─ Warrior (base warrior stats)
├─ Mage (base mage stats)
├─ Archer (base archer stats)
└─ Healer (base healer stats)

Clone base character → Customize name, appearance
Spawn multiple enemies by cloning prototype
```text

### 3. Database Connections
```javascript
ConnectionPrototype
├─ Development connection
├─ Testing connection
└─ Production connection

Clone connection with settings → Use immediately
Faster than establishing new connection
```text

### 4. Configuration Objects
```text
ConfigPrototype
├─ Default config (standard settings)
├─ Performance config (optimized)
└─ Debug config (verbose logging)

Clone appropriate config → Modify as needed
Consistent starting point for all instances
```

## How It Works
```javascript
┌────────────────────────────────────────────────────┐
│            Prototype Pattern Flow                   │
└────────────────────────────────────────────────────┘

Step 1: Create and configure prototype object
    ↓
Step 2: Store prototype (optional registry)
    ↓
Step 3: Client requests clone
    ↓
Step 4: Prototype clones itself
    ↓
Step 5: Return new object with same properties
    ↓
Step 6: Client modifies clone as needed
```javascript

## Benefits

**Performance**: Faster than creating from scratch (especially for expensive objects)

**Simplicity**: Avoid complex initialization logic

**Flexibility**: Clone and modify existing objects

**Runtime Configuration**: Add/remove prototypes at runtime

**Hide Complexity**: Client doesn't need to know construction details

**Reduced Subclassing**: Clone instead of creating many subclasses

## Drawbacks

**Deep Copy Complexity**: Circular references are problematic

**Clone Implementation**: Each class must implement cloning

**Hidden Dependencies**: Cloned objects may share references

**Memory**: Multiple copies consume memory

**Immutability Issues**: Hard with immutable objects

## Prototype Registry

Central repository of prototypes:
```text
┌────────────────────────────────────────────────────┐
│            Prototype Registry                       │
└────────────────────────────────────────────────────┘

Registry stores common prototypes:
├─ "default-config" → DefaultConfigPrototype
├─ "fast-config" → FastConfigPrototype
└─ "secure-config" → SecureConfigPrototype

Client usage:
1. Get prototype from registry
2. Clone it
3. Customize clone
4. Use customized object
```sql

## Prototype vs Other Creational Patterns
```text
┌────────────────────────────────────────────────────┐
│    Prototype vs Other Creational Patterns           │
└────────────────────────────────────────────────────┘

Prototype                    Factory Method
├─ Clones existing          ├─ Creates from scratch
├─ Object-based             ├─ Class-based
├─ Runtime copying          ├─ Compile-time creation
└─ Faster for complex       └─ Better for simple

Prototype                    Builder
├─ Clones and modifies      ├─ Builds step by step
├─ Quick copy               ├─ Flexible construction
├─ Less control             ├─ More control
└─ For similar objects      └─ For varied objects

Prototype                    Singleton
├─ Many instances           ├─ One instance
├─ Clone anytime            ├─ Shared instance
├─ Independent copies       ├─ Global state
└─ Different per copy       └─ Same for all
```text

## Common Use Cases
```javascript
┌────────────────────────────────────────────────────┐
│      Common Prototype Applications                  │
└────────────────────────────────────────────────────┘

Game Development
└─ Clone enemy types, weapons, characters

Graphics Applications
└─ Clone shapes, layers, styles

Configuration Management
└─ Clone environment settings

Testing
└─ Clone test data objects

Undo/Redo Systems
└─ Store object state snapshots

Object Pools
└─ Clone and return objects from pool

Caching Systems
└─ Clone cached objects for use
```

## Real-World Scenarios

### Scenario 1: Graphics Editor
```text
User creates complex shape with:
- Multiple layers
- Custom colors
- Effects applied
- Transformations

Instead of recreating:
→ Clone the shape
→ Position copy
→ Modify if needed
```text

### Scenario 2: Game Enemies
```text
Create one enemy prototype with:
- Health points
- Attack power
- AI behavior
- Animations loaded

Spawn 100 enemies:
→ Clone prototype 100 times
→ Faster than loading assets 100 times
→ Customize position, name per clone
```

### Scenario 3: Form Templates
```text
Company has standard form:
- Logo
- Header format
- Footer with legal text
- Standard fields

For each customer:
→ Clone template
→ Fill in customer details
→ Send personalized form
```text

## Implementing Clone Method

### Approach 1: Copy Constructor
```javascript
Create constructor that accepts same type:
- Takes existing object as parameter
- Copies all fields
- Creates new object with same values
```text

### Approach 2: Clone Method
```
Dedicated clone method:
- Returns copy of itself
- Handles deep/shallow copying
- Returns same type
```text

### Approach 3: Serialization
```sql
Serialize and deserialize:
- Convert object to JSON/binary
- Reconstruct from serialized form
- Automatic deep copy
- Slower but handles complexity
```

## Best Practices

**Implement Carefully**: Handle all fields correctly

**Deep vs Shallow**: Choose appropriate copy type

**Immutable Objects**: Consider if cloning makes sense

**Clone Arrays/Collections**: Don't forget nested structures

**Prototype Registry**: Use for frequently cloned objects

**Document Behavior**: Make clear what gets cloned

**Test Thoroughly**: Verify independence of clones

**Consider Alternatives**: Sometimes factory is simpler

## Common Mistakes

**Mistake 1: Shallow copy when deep needed**
```text
❌ Problem: Clones share nested objects
Result: Modifying one affects others

✅ Solution: Implement deep cloning for nested objects
```text

**Mistake 2: Forgetting to clone collections**
```
❌ Problem: Clone still references original array
Result: Changes to array affect both

✅ Solution: Clone all collections and nested objects
```text

**Mistake 3: Circular references**
```text
❌ Problem: Objects reference each other
Result: Infinite loop during cloning

✅ Solution: Track visited objects, handle cycles
```text

**Mistake 4: Not cloning mutable fields**
```
❌ Problem: Some fields stay references
Result: Partial independence

✅ Solution: Clone all mutable fields
```javascript

## When Prototype Shines

**Expensive Construction**: Database objects, network connections

**Many Similar Objects**: Game objects, UI components

**Runtime Configuration**: Dynamic object creation

**State Preservation**: Undo/redo, snapshots

**Object Pools**: Reusable object instances

## Pros and Cons Summary
```javascript
✅ Pros
├─ Faster than creating from scratch
├─ Reduces initialization complexity
├─ Flexible object creation
├─ Add/remove prototypes at runtime
├─ Reduces subclassing
└─ Hides complexity from client

❌ Cons
├─ Complex deep cloning
├─ Circular reference issues
├─ Each class needs clone method
├─ Can be memory intensive
├─ Shallow vs deep confusion
└─ Hard with immutable objects
```sql

## Key Takeaways

- **Clones objects** instead of creating new ones
- **Faster** for complex or expensive objects
- **Two types**: Shallow copy and deep copy
- **Prototype registry** stores common prototypes
- **Use when**: Object creation is expensive or complex
- **Don't use when**: Simple objects, cloning is harder than creating

**Remember**: Prototype is about efficiency through copying. If creating from scratch is simple and fast, you probably don't need this pattern. Use it when cloning saves significant time or complexity.

---
# Structural Patterns

Structural patterns explain how to assemble objects and classes into larger structures while keeping these structures flexible and efficient. They focus on composition and relationships between entities.

## What are Structural Patterns?

**Structural Patterns**: Deal with object composition and typically identify simple ways to realize relationships between different objects.

**Core Idea**: How to compose objects to form larger structures

Think of **building construction**:
- Individual materials (wood, steel, glass)
- Combined to form larger structures (walls, rooms, buildings)
- Different ways to combine them for different purposes

## Overview of Structural Patterns
```text
┌────────────────────────────────────────────────────┐
│           Structural Patterns Overview              │
└────────────────────────────────────────────────────┘

Adapter
└─ Makes incompatible interfaces work together

Facade
└─ Provides simplified interface to complex system

Decorator
└─ Adds behavior to objects dynamically

Composite
└─ Treats individual and groups uniformly

Proxy
└─ Provides surrogate or placeholder for another object

Bridge
└─ Separates abstraction from implementation

Flyweight
└─ Shares common data between multiple objects
```javascript

---

# Adapter Pattern

The Adapter pattern allows objects with incompatible interfaces to collaborate by converting the interface of one class into an interface expected by clients.

## What is Adapter Pattern?

**Adapter Pattern**: Converts one interface into another interface clients expect.

**Core Idea**: Make incompatible things work together

Think of **power adapters**:
- US plug won't fit European socket
- Adapter converts US plug to work with European socket
- Device works without modification

## Problem It Solves

**Without Adapter**:
```javascript
New library with different interface:

// Your code expects
payment.processPayment(amount);

// New library provides
newPayment.makeTransaction(amount, currency, metadata);

// Incompatible! Can't use directly
```

**With Adapter**:
```javascript
Adapter translates between interfaces:

PaymentAdapter wraps new library
└─ Implements your expected interface
└─ Internally calls new library's interface

// Your code unchanged
payment.processPayment(amount);
```javascript

## When to Use Adapter

**Use When**:
- Want to use existing class with incompatible interface
- Need to create reusable class with unrelated classes
- Legacy code needs to work with new code
- Third-party library has different interface

**Don't Use When**:
- Can modify the source code directly
- Interfaces are already compatible
- Adds unnecessary complexity

## Structure
```javascript
┌──────────────┐
│    Client    │
└──────┬───────┘
       │ uses
       ▼
┌──────────────┐
│    Target    │ (Interface client expects)
└──────△───────┘
       │
       │ implements
       │
┌──────┴───────┐
│   Adapter    │
├──────────────┤
│ - adaptee    │ ← Wraps incompatible object
├──────────────┤
│ + operation()│ ← Translates calls
└──────┬───────┘
       │ delegates to
       ▼
┌──────────────┐
│   Adaptee    │ (Incompatible interface)
├──────────────┤
│ + specificOp()│
└──────────────┘
```text

## Real-World Examples

### 1. Payment Gateway Integration
```text
Your System expects:
└─ processPayment(amount)

Stripe API provides:
└─ charge(amount, currency, customer)

StripeAdapter:
└─ processPayment(amount) {
      stripe.charge(amount, "USD", defaultCustomer)
    }

Now your system can use Stripe seamlessly
```text

### 2. Data Format Conversion
```javascript
Your App expects JSON:
└─ parseData(jsonString)

Legacy System returns XML:
└─ getDataInXML()

XMLToJSONAdapter:
└─ parseData(data) {
      xmlData = legacySystem.getDataInXML()
      return convertXMLtoJSON(xmlData)
    }
```

### 3. Media Players
```text
Audio Player expects:
└─ play(audioFile)

Different formats need different players:
└─ MP3Player, VLCPlayer, MP4Player

MediaAdapter:
└─ Wraps specific player based on format
└─ Provides uniform play() interface
```text

## Types of Adapters

### Class Adapter (Inheritance)
```javascript
Adapter extends Adaptee
└─ Inherits Adaptee's implementation
└─ Implements Target interface
└─ Uses inheritance
```text

### Object Adapter (Composition)
```javascript
Adapter contains Adaptee
└─ Holds reference to Adaptee
└─ Implements Target interface
└─ Uses composition (preferred)
```

## Benefits

**Reusability**: Use existing classes without modification

**Flexibility**: Add new adapters without changing existing code

**Single Responsibility**: Separates interface conversion from business logic

**Open/Closed**: Add new types without modifying client code

## Drawbacks

**Complexity**: Additional layer of abstraction

**Performance**: Extra method calls through adapter

**Maintenance**: Another class to maintain

## Key Takeaways

- **Bridges incompatible interfaces**
- **Client code unchanged**
- **Prefer composition** over inheritance
- **Use when**: Integrating third-party libraries, legacy systems

---

# Facade Pattern

The Facade pattern provides a simplified interface to a complex subsystem, making it easier to use.

## What is Facade Pattern?

**Facade Pattern**: Provides a unified, simplified interface to a set of interfaces in a subsystem.

**Core Idea**: Hide complexity behind a simple interface

Think of a **car dashboard**:
- Simple controls: steering wheel, pedals, buttons
- Hides complex systems: engine, transmission, fuel injection
- Driver doesn't need to know internal details

## Problem It Solves

**Without Facade**:
```javascript
Complex subsystem with many interactions:

// Client needs to know all details
system.initialize();
database.connect();
cache.warmup();
logger.configure();
api.authenticate();
monitor.start();

// Too complex for simple task
```text

**With Facade**:
```javascript
Simple interface hides complexity:

ApplicationFacade.start();

// One call does everything
// Hides all complexity
```text

## When to Use Facade

**Use When**:
- Complex system needs simplified interface
- Many dependencies between clients and implementation
- Want to layer subsystems
- Need entry point to complex functionality

**Don't Use When**:
- Subsystem is already simple
- Clients need direct access to subsystem
- Facade becomes too complex itself

## Structure
```text
┌──────────────┐
│    Client    │
└──────┬───────┘
       │ uses simple interface
       ▼
┌──────────────┐
│    Facade    │
├──────────────┤
│ + operation()│ ← Simple method
└──────┬───────┘
       │ coordinates
       │
   ┌───┼───┬───────┐
   │   │   │       │
   ▼   ▼   ▼       ▼
┌────┐┌────┐┌────┐┌────┐
│Sub ││Sub ││Sub ││Sub │ Complex subsystems
│ A  ││ B  ││ C  ││ D  │
└────┘└────┘└────┘└────┘
```text

## Real-World Examples

### 1. Home Theater System
```
Complex Components:
├─ DVD Player
├─ Projector
├─ Sound System
├─ Lights
└─ Screen

HomeTheaterFacade:
└─ watchMovie()
    ├─ lights.dim()
    ├─ screen.down()
    ├─ projector.on()
    ├─ soundSystem.on()
    └─ dvdPlayer.play()

One simple call instead of many
```sql

### 2. Order Processing
```javascript
Complex Process:
├─ Validate inventory
├─ Process payment
├─ Update database
├─ Send confirmation email
└─ Notify shipping

OrderFacade:
└─ placeOrder(order)
    // Handles all steps internally
    // Client just calls one method
```

### 3. File Compression
```javascript
Complex Steps:
├─ Read file
├─ Compress data
├─ Create archive
├─ Write to disk
└─ Clean up temp files

CompressionFacade:
└─ compressFile(filename)
    // All complexity hidden
    // Simple interface for user
```text

## Benefits

**Simplicity**: Easy to use complex subsystems

**Decoupling**: Reduces dependencies on subsystem

**Layering**: Helps structure subsystems into layers

**Flexibility**: Can change subsystem without affecting clients

## Drawbacks

**God Object Risk**: Facade can become too large

**Limited Access**: May restrict advanced features

**Another Layer**: Adds abstraction overhead

## Facade vs Adapter
```text
┌────────────────────────────────────────────────────┐
│           Facade vs Adapter                         │
└────────────────────────────────────────────────────┘

Facade                        Adapter
├─ Simplifies interface       ├─ Converts interface
├─ Works with many classes    ├─ Works with one class
├─ Provides simpler interface ├─ Makes compatible interface
├─ Intent: Simplify          ├─ Intent: Compatibility
└─ Hides complexity          └─ Translates calls
```javascript

## Key Takeaways

- **Simplifies complex systems**
- **Provides unified interface**
- **Reduces coupling**
- **Use when**: Dealing with complex subsystems

---

# Decorator Pattern

The Decorator pattern attaches additional responsibilities to objects dynamically, providing a flexible alternative to subclassing for extending functionality.

## What is Decorator Pattern?

**Decorator Pattern**: Adds new functionality to objects without modifying their structure.

**Core Idea**: Wrap objects to add behavior dynamically

Think of **dressing up**:
- Start with basic clothes
- Add layers: jacket, scarf, hat
- Each layer adds functionality
- Can add/remove layers anytime

## Problem It Solves

**Without Decorator**:
```javascript
Need many subclasses for combinations:

Coffee
├─ CoffeeWithMilk
├─ CoffeeWithSugar
├─ CoffeeWithMilkAndSugar
├─ CoffeeWithMilkAndSugarAndWhippedCream
└─ ... (exponential combinations)

Subclass explosion!
```

**With Decorator**:
```javascript
Wrap objects dynamically:

coffee = new Coffee();
coffee = new MilkDecorator(coffee);
coffee = new SugarDecorator(coffee);
coffee = new WhippedCreamDecorator(coffee);

Flexible combinations at runtime
```text

## When to Use Decorator

**Use When**:
- Need to add responsibilities to objects dynamically
- Want to extend object without subclassing
- Behavior combinations need flexibility
- Subclassing would create too many classes

**Don't Use When**:
- Object's identity must not change
- Need to remove decorators frequently
- Order of decorators doesn't matter (use composition)

## Structure
```text
┌──────────────┐
│  Component   │ (Interface)
├──────────────┤
│ + operation()│
└──────△───────┘
       │
   ┌───┴────────────┐
   │                │
┌──┴────────┐  ┌───┴────────┐
│ Concrete  │  │ Decorator  │ (Abstract)
│ Component │  ├────────────┤
└───────────┘  │ - component│
               ├────────────┤
               │+operation()│
               └──────△─────┘
                      │
               ┌──────┴──────┐
               │             │
        ┌──────┴─────┐ ┌────┴──────┐
        │ConcreteA   │ │ConcreteB  │
        │Decorator   │ │Decorator  │
        └────────────┘ └───────────┘
```text

## Real-World Examples

### 1. Coffee Shop
```
Base: Simple Coffee ($2)

Add decorators:
├─ + Milk ($0.50)
├─ + Sugar ($0.25)
├─ + Whipped Cream ($0.75)
└─ + Caramel ($0.50)

Order: Coffee with Milk and Caramel
Cost: $2 + $0.50 + $0.50 = $3

Flexible combinations, calculated dynamically
```text

### 2. Text Formatting
```javascript
Base: Plain Text

Add decorators:
├─ Bold
├─ Italic
├─ Underline
└─ Color

text = new PlainText("Hello");
text = new BoldDecorator(text);
text = new ItalicDecorator(text);

Result: <b><i>Hello</i></b>
```

### 3. Data Streams
```javascript
Base: FileStream

Add decorators:
├─ BufferedStream (adds buffering)
├─ CompressedStream (adds compression)
└─ EncryptedStream (adds encryption)

stream = new FileStream("data.txt");
stream = new CompressedStream(stream);
stream = new EncryptedStream(stream);

Data is compressed then encrypted automatically
```javascript

## Benefits

**Flexibility**: Add/remove responsibilities at runtime

**Single Responsibility**: Each decorator has one concern

**Open/Closed**: Extend without modifying existing code

**Composition**: Combine decorators in any order

## Drawbacks

**Complexity**: Many small objects

**Order Matters**: Decorator order can affect behavior

**Identity**: Decorated object != original object

**Debugging**: Stack of decorators hard to debug

## Key Takeaways

- **Adds behavior dynamically**
- **Wraps objects**
- **Flexible combinations**
- **Use when**: Need runtime behavior extension

---

# Composite Pattern

The Composite pattern composes objects into tree structures to represent part-whole hierarchies, allowing clients to treat individual objects and compositions uniformly.

## What is Composite Pattern?

**Composite Pattern**: Treats individual objects and compositions of objects uniformly.

**Core Idea**: Tree structure where leaves and branches treated the same

Think of **file system**:
- Files (leaves) and Folders (composite)
- Both can be moved, copied, deleted
- Folder contains files and other folders
- Same operations work on both

## Problem It Solves

**Without Composite**:
```javascript
Different handling for items and groups:

if (item is File) {
    item.open();
} else if (item is Folder) {
    for (child in item.children) {
        // Recursive handling
    }
}

// Complex and error-prone
```text

**With Composite**:
```javascript
Uniform handling:

item.open();  // Works for File or Folder

Folder handles recursion internally
```text

## When to Use Composite

**Use When**:
- Need tree structures (hierarchy)
- Want clients to treat parts and wholes uniformly
- Need recursive composition
- Part-whole relationships exist

**Don't Use When**:
- Flat structure (no hierarchy)
- Different operations for leaf vs composite
- Adds unnecessary complexity

## Structure
```text
┌──────────────┐
│  Component   │ (Interface)
├──────────────┤
│ + operation()│
└──────△───────┘
       │
   ┌───┴────────────┐
   │                │
┌──┴────┐      ┌────┴─────┐
│ Leaf  │      │Composite │
├───────┤      ├──────────┤
│+op()  │      │-children │
└───────┘      │+op()     │
               │+add()    │
               │+remove() │
               └──────────┘
```

## Real-World Examples

### 1. File System
```text
FileSystemItem (Component)
├─ File (Leaf)
│   └─ getSize() returns file size
└─ Folder (Composite)
    ├─ contains Files and Folders
    └─ getSize() returns sum of all contents

folder.getSize() works recursively
```text

### 2. Organization Hierarchy
```text
Employee (Component)
├─ Developer (Leaf)
└─ Manager (Composite)
    └─ has team of Employees

manager.getSalaryTotal()
└─ Includes all team members recursively
```

### 3. Graphic Shapes
```text
Graphic (Component)
├─ Circle, Rectangle (Leaf)
└─ Group (Composite)
    └─ contains multiple Graphics

group.draw()
└─ Draws all shapes in group
```text

## Benefits

**Uniform Treatment**: Same interface for all objects

**Flexibility**: Easy to add new component types

**Simplifies Client**: No need to distinguish leaf/composite

**Recursive**: Naturally handles tree structures

## Drawbacks

**Over-Generalization**: Forces common interface

**Type Safety**: Hard to restrict child types

**Complexity**: May be overkill for simple structures

## Key Takeaways

- **Tree structures**
- **Uniform treatment** of parts and wholes
- **Recursive composition**
- **Use when**: Hierarchical structures exist

---

# Proxy Pattern

The Proxy pattern provides a surrogate or placeholder for another object to control access to it.

## What is Proxy Pattern?

**Proxy Pattern**: Provides a substitute or placeholder that controls access to another object.

**Core Idea**: Intermediary that controls access

Think of **security guard**:
- Guards building entrance
- Checks credentials before allowing entry
- Controls who accesses what
- Real building behind the guard

## Problem It Solves

**Without Proxy**:
```javascript
Direct access to expensive resources:

image = new HighResImage("large.jpg");
// Loads immediately, even if not displayed
// Wastes memory and time
```javascript

**With Proxy**:
```javascript
Controlled access:

image = new ImageProxy("large.jpg");
// Doesn't load yet
image.display();
// Loads only when actually needed
```

## When to Use Proxy

**Use When**:
- Need lazy initialization (load on demand)
- Need access control (security)
- Need remote object access (network)
- Need logging/monitoring
- Need caching

**Don't Use When**:
- Direct access is sufficient
- Adds unnecessary overhead
- No control/optimization needed

## Types of Proxies

### 1. Virtual Proxy
```text
Controls access to expensive resources

Example: Lazy-loading images
└─ Create proxy immediately
└─ Load actual image when needed
└─ Saves memory and time
```text

### 2. Protection Proxy
```text
Controls access based on permissions

Example: Document access
└─ Check user permissions
└─ Allow/deny operations
└─ Enforce security rules
```

### 3. Remote Proxy
```text
Represents object in different address space

Example: Remote service
└─ Local proxy object
└─ Handles network communication
└─ Represents remote object
```text

### 4. Caching Proxy
```text
Caches results of expensive operations

Example: Database query
└─ Check cache first
└─ Query database if not cached
└─ Store result in cache
```

### 5. Logging Proxy
```text
Logs access to object

Example: API calls
└─ Log before calling real object
└─ Call real object
└─ Log after completion
```text

## Structure
```text
┌──────────────┐
│   Subject    │ (Interface)
├──────────────┤
│ + operation()│
└──────△───────┘
       │
   ┌───┴────────────┐
   │                │
┌──┴─────────┐ ┌───┴─────┐
│RealSubject │ │  Proxy  │
├────────────┤ ├─────────┤
│+operation()│ │-subject │
└────────────┘ │+operation()│
               └─────────┘
```javascript

## Real-World Examples

### 1. Image Loading
```javascript
ImageProxy:
└─ Holds filename
└─ display() {
      if (!realImage) {
          realImage = new RealImage(filename);
      }
      realImage.display();
   }

Only loads image when display() called
```

### 2. Bank Account Access
```javascript
BankAccountProxy:
└─ Checks user permissions
└─ withdraw(amount) {
      if (user.hasPermission()) {
          realAccount.withdraw(amount);
      } else {
          throw new SecurityException();
      }
   }

Controls who can access account
```javascript

### 3. Remote Service
```javascript
PaymentServiceProxy:
└─ Handles network communication
└─ processPayment(amount) {
      // Serialize request
      // Send over network
      // Deserialize response
      return response;
   }

Hides network complexity
```sql

## Benefits

**Lazy Initialization**: Create expensive objects only when needed

**Access Control**: Restrict access based on rules

**Remote Access**: Transparent remote object access

**Logging**: Track object usage

**Caching**: Improve performance

## Drawbacks

**Complexity**: Additional layer

**Performance**: Extra method call overhead

**Indirection**: Makes code less direct

## Proxy vs Decorator
```text
┌────────────────────────────────────────────────────┐
│           Proxy vs Decorator                        │
└────────────────────────────────────────────────────┘

Proxy                         Decorator
├─ Controls access            ├─ Adds behavior
├─ Same interface             ├─ Same interface
├─ Can create object lazily   ├─ Wraps existing object
├─ Intent: Control           ├─ Intent: Enhancement
└─ Manages lifecycle         └─ Adds responsibilities
```text

## Key Takeaways

- **Controls access** to objects
- **Many types**: Virtual, Protection, Remote, Caching
- **Transparent** to client
- **Use when**: Need controlled access or lazy loading

---

# Bridge Pattern

The Bridge pattern decouples an abstraction from its implementation so that the two can vary independently.

## What is Bridge Pattern?

**Bridge Pattern**: Separates abstraction from implementation, allowing both to change independently.

**Core Idea**: Decouple what from how

Think of **remote control and devices**:
- Remote control (abstraction)
- TV, Radio, AC (implementations)
- Same remote works with different devices
- Can change remote or device independently

## Problem It Solves

**Without Bridge**:
```
Class explosion with combinations:

RemoteControl
├─ TVRemote
│   ├─ SonyTVRemote
│   └─ SamsungTVRemote
└─ RadioRemote
    ├─ SonyRadioRemote
    └─ SamsungRadioRemote

N abstractions × M implementations = N×M classes
```text

**With Bridge**:
```text
Separate hierarchies:

RemoteControl → Device
├─ BasicRemote
└─ AdvancedRemote

Device
├─ TV
└─ Radio

N + M classes instead of N×M
```text

## When to Use Bridge

**Use When**:
- Want to avoid permanent binding between abstraction and implementation
- Both abstraction and implementation should be extensible
- Changes in implementation shouldn't affect clients
- Need to switch implementations at runtime

**Don't Use When**:
- Only one implementation exists
- Abstraction and implementation won't change
- Adds unnecessary complexity

## Structure
```text
┌──────────────┐
│ Abstraction  │
├──────────────┤
│ -implementor │ ───────┐
├──────────────┤        │
│ + operation()│        │ uses
└──────△───────┘        │
       │                │
       │                ▼
┌──────┴───────┐  ┌──────────────┐
│  Refined     │  │ Implementor  │ (Interface)
│ Abstraction  │  ├──────────────┤
└──────────────┘  │+ implement() │
                  └──────△───────┘
                         │
                    ┌────┴────┐
                    │         │
            ┌───────┴──┐ ┌────┴──────┐
            │ConcreteA │ │ConcreteB  │
            │Implement │ │Implement  │
            └──────────┘ └───────────┘
```

## Real-World Examples

### 1. Device and Remote
```javascript
Remote (Abstraction)
├─ BasicRemote
└─ AdvancedRemote

Device (Implementation)
├─ TV
├─ Radio
└─ AirConditioner

remote = new AdvancedRemote(new TV());
remote.powerOn();
// Works with any device
```javascript

### 2. Shape and Color
```javascript
Shape (Abstraction)
├─ Circle
└─ Square

Color (Implementation)
├─ Red
└─ Blue

circle = new Circle(new Red());
// Can change color without changing shape
```javascript

### 3. Message and Sender
```javascript
Message (Abstraction)
├─ TextMessage
└─ EmailMessage

Sender (Implementation)
├─ SMSSender
├─ EmailSender
└─ PushSender

message = new TextMessage(new SMSSender());
// Same message, different sending method
```javascript

## Benefits

**Decoupling**: Abstraction independent of implementation

**Extensibility**: Extend abstraction and implementation separately

**Runtime Binding**: Switch implementations at runtime

**Reduced Subclassing**: Avoids class explosion

## Drawbacks

**Complexity**: More classes and interfaces

**Indirection**: Extra layer between client and implementation

**Design Effort**: Requires upfront planning

## Bridge vs Adapter
```javascript
┌────────────────────────────────────────────────────┐
│           Bridge vs Adapter                         │
└────────────────────────────────────────────────────┘

Bridge                        Adapter
├─ Designed upfront           ├─ Applied to existing code
├─ Separates abstraction      ├─ Makes things work together
├─ Both sides can vary        ├─ Converts one interface
├─ Intent: Decouple          ├─ Intent: Compatibility
└─ Prevents class explosion  └─ Solves incompatibility
```

## Key Takeaways

- **Separates abstraction from implementation**
- **Both can vary independently**
- **Avoids class explosion**
- **Use when**: Multiple dimensions of variation

---

# Flyweight Pattern

The Flyweight pattern minimizes memory usage by sharing as much data as possible with similar objects.

## What is Flyweight Pattern?

**Flyweight Pattern**: Shares common data between multiple objects to save memory.

**Core Idea**: Share what's common, store what's unique

Think of **text editor**:
- Each character has font, size, color (shared)
- Each character has position (unique)
- Don't create new font object for every character
- Share font objects among characters

## Problem It Solves

**Without Flyweight**:
```javascript
Creating many similar objects:

// 1 million trees in forest
for (i = 0; i < 1000000; i++) {
    tree = new Tree(
        texture,  // Same for many trees
        color,    // Same for many trees
        x,        // Unique
        y         // Unique
    );
}

// Huge memory waste on repeated data
```text

**With Flyweight**:
```javascript
Share common data:

TreeType (shared state):
└─ texture, color (shared among many trees)

Tree (unique state):
└─ x, y, treeType reference

// Dramatically reduces memory usage
```

## When to Use Flyweight

**Use When**:
- Application uses large number of objects
- Objects have shared state
- Memory is a concern
- Object identity doesn't matter

**Don't Use When**:
- Few objects exist
- No shared state
- Objects need unique identity
- Adds unnecessary complexity

## Structure
```text
┌────────────────┐
│  Flyweight     │ (Interface)
├────────────────┤
│ + operation()  │
└────────△───────┘
         │
    ┌────┴────┐
    │         │
┌───┴──────┐ ┌┴──────────┐
│Concrete  │ │Unshared   │
│Flyweight │ │Flyweight  │
├──────────┤ ├───────────┤
│intrinsic │ │all state  │
│state     │ │           │
└──────────┘ └───────────┘

┌──────────────────┐
│FlyweightFactory  │
├──────────────────┤
│ - flyweights     │
│ + getFlyweight() │
└──────────────────┘
```text

## Types of State

### Intrinsic State (Shared)
```text
Data that's identical for many objects
└─ Can be shared
└─ Stored in Flyweight

Example: Tree texture and color
```text

### Extrinsic State (Unique)
```
Data that's unique to each object
└─ Cannot be shared
└─ Passed to Flyweight methods

Example: Tree position (x, y)
```text

## Real-World Examples

### 1. Text Editor
```text
CharacterFlyweight (shared):
└─ font, size, color

CharacterPosition (unique):
└─ x, y, character reference

10,000 characters, but only 100 unique font combinations
Saves massive memory
```text

### 2. Game Development
```
ParticleType (shared):
└─ texture, color, effects

Particle (unique):
└─ position, velocity, particleType reference

10,000 particles, but only 10 particle types
```text

### 3. Icon System
```text
IconImage (shared):
└─ image data

IconInstance (unique):
└─ position, size, iconImage reference

Same icon used multiple times on screen
```

## Benefits

**Memory Efficiency**: Dramatically reduces memory usage

**Performance**: Fewer objects to create and manage

**Scalability**: Handle massive numbers of objects

## Drawbacks

**Complexity**: More complex code

**Runtime Cost**: Lookup in factory

**Trade-off**: CPU time for memory savings

**Threading**: Shared state needs thread safety

## Implementation Considerations

### Flyweight Factory
```text
Manages flyweight pool:
└─ Creates flyweights
└─ Returns existing if available
└─ Ensures sharing
```text

### Immutability
```
Flyweights should be immutable:
└─ Shared state shouldn't change
└─ Prevents unwanted side effects
└─ Thread-safe by nature
```text

## Key Takeaways

- **Shares common data** between objects
- **Separates intrinsic** (shared) from extrinsic (unique) state
- **Saves memory** for large numbers of similar objects
- **Use when**: Many objects with shared characteristics

---

# Structural Patterns Summary
```text
┌────────────────────────────────────────────────────┐
│        Structural Patterns Quick Reference          │
└────────────────────────────────────────────────────┘

Adapter
└─ Makes incompatible interfaces work together
└─ Use: Third-party integration, legacy code

Facade
└─ Simplifies complex subsystems
└─ Use: Complex APIs, multiple components

Decorator
└─ Adds behavior dynamically
└─ Use: Runtime feature additions, flexible combinations

Composite
└─ Tree structures, uniform treatment
└─ Use: Hierarchies, part-whole relationships

Proxy
└─ Controls access to objects
└─ Use: Lazy loading, access control, remote objects

Bridge
└─ Separates abstraction from implementation
└─ Use: Multiple dimensions of variation

Flyweight
└─ Shares data to save memory
└─ Use: Large numbers of similar objects
```text

## Choosing the Right Pattern
```
Need to integrate incompatible code?
└─> Adapter

Complex subsystem needs simple interface?
└─> Facade

Add behavior at runtime?
└─> Decorator

Tree-like hierarchy?
└─> Composite

Control access or lazy load?
└─> Proxy

Multiple variations of abstraction and implementation?
└─> Bridge

Many similar objects consuming memory?
└─> Flyweight
```sql

All structural patterns help organize relationships between objects to create flexible, maintainable structures.

---
# Behavioral Patterns

Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects. They describe not just patterns of objects or classes but also the patterns of communication between them.

## What are Behavioral Patterns?

**Behavioral Patterns**: Focus on communication between objects and how responsibilities are distributed.

**Core Idea**: How objects interact and distribute responsibilities

Think of **restaurant operations**:
- Chef prepares food (responsibility)
- Waiter serves customers (communication)
- Cashier handles payment (interaction)
- Each has a role, all work together

## Overview of Behavioral Patterns
```text
┌────────────────────────────────────────────────────┐
│          Behavioral Patterns Overview               │
└────────────────────────────────────────────────────┘

Strategy
└─ Defines family of algorithms, makes them interchangeable

Iterator
└─ Accesses elements sequentially without exposing structure

Observer
└─ Notifies multiple objects when state changes

Command
└─ Encapsulates requests as objects

State
└─ Changes behavior when internal state changes

Template Method
└─ Defines algorithm skeleton, lets subclasses override steps

Chain of Responsibility
└─ Passes request along chain of handlers

Visitor
└─ Adds operations to objects without modifying them

Mediator
└─ Reduces direct communication between objects

Memento
└─ Captures and restores object state
```javascript

---

# Strategy Pattern

The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. It lets the algorithm vary independently from clients that use it.

## What is Strategy Pattern?

**Strategy Pattern**: Defines a family of interchangeable algorithms and lets the client choose which one to use.

**Core Idea**: Select algorithm at runtime

Think of **navigation apps**:
- Same destination, different routes
- Car route (fastest roads)
- Walking route (pedestrian paths)
- Bike route (bike lanes)
- Choose strategy based on preference

## Problem It Solves

**Without Strategy**:
```javascript
Algorithm selection using conditionals:

if (type === "car") {
    // Car routing logic
} else if (type === "walk") {
    // Walking routing logic
} else if (type === "bike") {
    // Bike routing logic
}

// Hard to maintain
// Can't add new strategies easily
// Violates Open/Closed Principle
```

**With Strategy**:
```javascript
Each algorithm is separate class:

CarStrategy
WalkStrategy
BikeStrategy

navigator.setStrategy(new CarStrategy());
navigator.calculateRoute();

// Easy to add new strategies
// Clean, maintainable code
```text

## When to Use Strategy

**Use When**:
- Multiple algorithms for same task
- Need to switch algorithms at runtime
- Want to avoid conditional statements
- Algorithms have different implementations
- Want to hide algorithm complexity

**Don't Use When**:
- Only one algorithm exists
- Algorithms don't change
- Simple if-else is sufficient
- Adds unnecessary complexity

## Structure
```text
┌──────────────┐
│   Context    │
├──────────────┤
│ - strategy   │
├──────────────┤
│ + setStrategy│
│ + execute()  │
└──────┬───────┘
       │ uses
       ▼
┌──────────────┐
│   Strategy   │ (Interface)
├──────────────┤
│ + algorithm()│
└──────△───────┘
       │
   ┌───┴────────┬─────────┐
   │            │         │
┌──┴──────┐ ┌──┴──────┐ ┌┴────────┐
│ConcreteA│ │ConcreteB│ │ConcreteC│
│Strategy │ │Strategy │ │Strategy │
├─────────┤ ├─────────┤ ├─────────┤
│+algo()  │ │+algo()  │ │+algo()  │
└─────────┘ └─────────┘ └─────────┘
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│        Strategy Pattern Components                  │
└────────────────────────────────────────────────────┘

Strategy Interface
└─ Defines common interface for all algorithms

Concrete Strategies
└─ Implement different algorithms

Context
└─ Maintains reference to strategy
└─ Delegates work to strategy object

Client
└─ Selects and provides strategy to context
```text

## Real-World Examples

### 1. Payment Processing
```
Payment Strategy Interface:
└─ pay(amount)

Concrete Strategies:
├─ CreditCardStrategy
│   └─ pay() → process credit card payment
├─ PayPalStrategy
│   └─ pay() → process PayPal payment
├─ CryptoStrategy
│   └─ pay() → process cryptocurrency payment
└─ CashStrategy
    └─ pay() → process cash payment

Checkout context:
└─ setPaymentStrategy(strategy)
└─ processPayment(amount)

User selects payment method at runtime
```text

### 2. Sorting Algorithms
```text
Sort Strategy Interface:
└─ sort(data)

Concrete Strategies:
├─ QuickSort
│   └─ sort() → implements quicksort
├─ MergeSort
│   └─ sort() → implements mergesort
├─ BubbleSort
│   └─ sort() → implements bubblesort
└─ HeapSort
    └─ sort() → implements heapsort

Sorter context:
└─ setStrategy(strategy)
└─ sort(data)

Choose algorithm based on data size/type
```text

### 3. Compression
```
Compression Strategy Interface:
└─ compress(file)

Concrete Strategies:
├─ ZipCompression
│   └─ compress() → ZIP format
├─ RarCompression
│   └─ compress() → RAR format
├─ GzipCompression
│   └─ compress() → GZIP format
└─ SevenZipCompression
    └─ compress() → 7Z format

Compressor context:
└─ setStrategy(strategy)
└─ compress(file)

User chooses compression format
```text

### 4. Discount Calculation
```javascript
Discount Strategy Interface:
└─ calculateDiscount(amount)

Concrete Strategies:
├─ NoDiscount
│   └─ calculateDiscount() → return 0
├─ PercentageDiscount
│   └─ calculateDiscount() → amount * percentage
├─ FixedDiscount
│   └─ calculateDiscount() → fixed amount off
└─ BuyOneGetOneFree
    └─ calculateDiscount() → 50% off

Shopping cart:
└─ setDiscountStrategy(strategy)
└─ calculateTotal()

Different discount strategies for different customers
```text

### 5. Travel Routes
```text
Route Strategy Interface:
└─ calculateRoute(start, end)

Concrete Strategies:
├─ CarRoute
│   └─ calculateRoute() → fastest roads, highways
├─ WalkRoute
│   └─ calculateRoute() → pedestrian paths, shortcuts
├─ BikeRoute
│   └─ calculateRoute() → bike lanes, safe routes
└─ PublicTransportRoute
    └─ calculateRoute() → bus/train routes

Navigator context:
└─ setRouteStrategy(strategy)
└─ navigate(start, end)

User selects travel mode
```

## Benefits

**Open/Closed Principle**: Add new strategies without modifying existing code

**Eliminates Conditionals**: No if-else or switch statements

**Runtime Flexibility**: Switch algorithms at runtime

**Single Responsibility**: Each algorithm in separate class

**Testability**: Easy to test strategies independently

**Encapsulation**: Algorithm details hidden from client

## Drawbacks

**More Classes**: Each strategy is a separate class

**Client Awareness**: Client must know about different strategies

**Communication Overhead**: Extra objects and method calls

**Overkill**: Too complex for simple cases

## Strategy Pattern Flow
```text
┌────────────────────────────────────────────────────┐
│            Strategy Pattern Flow                    │
└────────────────────────────────────────────────────┘

Step 1: Client creates strategy
    ↓
Step 2: Client passes strategy to context
    ↓
Step 3: Context stores strategy reference
    ↓
Step 4: Context delegates work to strategy
    ↓
Step 5: Strategy executes algorithm
    ↓
Step 6: Result returned to client
```text

## Strategy vs State Pattern
```text
┌────────────────────────────────────────────────────┐
│           Strategy vs State Pattern                 │
└────────────────────────────────────────────────────┘

Strategy                      State
├─ Client chooses strategy    ├─ Object changes state
├─ Algorithms interchangeable ├─ Behaviors change with state
├─ Intent: Algorithm choice   ├─ Intent: State-dependent behavior
├─ Client aware of strategies ├─ Client unaware of states
└─ External selection         └─ Internal state changes
```text

## Implementation Variations

### 1. Simple Strategy
```text
Just strategy interface and implementations
Client sets strategy explicitly
```

### 2. Strategy with Default
```text
Context has default strategy
Client can override if needed
```sql

### 3. Strategy Factory
```text
Factory creates appropriate strategy
Based on configuration or parameters
Hides strategy selection from client
```

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│       Common Strategy Pattern Applications          │
└────────────────────────────────────────────────────┘

Payment Systems
└─ Multiple payment methods

Sorting/Searching
└─ Different algorithms for different data

Validation
└─ Different validation rules

Pricing/Discounts
└─ Various pricing strategies

Navigation
└─ Different route calculation methods

Compression
└─ Multiple compression formats

Authentication
└─ Different authentication methods

Logging
└─ Log to different destinations

Export Formats
└─ Export data in various formats
```sql

## Best Practices

**Interface Over Implementation**: Depend on strategy interface, not concrete strategies

**Immutable Strategies**: Make strategies stateless when possible

**Meaningful Names**: Use descriptive strategy names (CreditCardPayment, not Strategy1)

**Factory for Selection**: Use factory to select appropriate strategy

**Document Strategies**: Clearly document when to use each strategy

**Keep Simple**: Don't over-engineer with too many strategies

**Single Responsibility**: Each strategy does one thing well

## Real Implementation Example
```javascript
Payment System Flow:

1. User selects payment method
   └─ CreditCard / PayPal / Crypto

2. System creates appropriate strategy
   └─ strategy = new CreditCardStrategy()

3. Strategy passed to checkout
   └─ checkout.setPaymentStrategy(strategy)

4. Process payment
   └─ checkout.processPayment(amount)

5. Strategy executes algorithm
   └─ strategy.pay(amount)

6. Result returned
   └─ success/failure
```

## Pros and Cons Summary
```javascript
✅ Pros
├─ Easy to add new algorithms
├─ Eliminates conditional logic
├─ Runtime flexibility
├─ Encapsulates algorithms
├─ Promotes Open/Closed Principle
└─ Easy to test

❌ Cons
├─ Increases number of classes
├─ Client must understand strategies
├─ May be overkill for simple cases
├─ Communication overhead
└─ Strategy selection responsibility
```javascript

## When to Use Strategy Pattern

**Use When You See**:
- "If type is X, do algorithm A, if Y do B..."
- Multiple ways to perform same operation
- Need to switch behavior at runtime
- Want to avoid complex conditionals
- Algorithms may change independently

**Don't Use When**:
- Only one algorithm exists
- Algorithm won't change
- Simple if-else is clearer
- Performance is critical (small overhead)

## Key Takeaways

- **Defines family of algorithms** that are interchangeable
- **Encapsulates each algorithm** in separate class
- **Client chooses** which algorithm to use
- **Enables runtime switching** of algorithms
- **Eliminates conditionals** and promotes clean code
- **Use when**: Multiple algorithms for same task
- **Don't use when**: Only one algorithm or simple logic

**Remember**: Strategy pattern is about having multiple ways to do the same thing and letting the client choose which way at runtime. If you don't need multiple algorithms or runtime selection, you probably don't need Strategy pattern.

---

# Iterator Pattern

The Iterator pattern provides a way to access elements of a collection sequentially without exposing its underlying representation.

## What is Iterator Pattern?

**Iterator Pattern**: Provides sequential access to elements of a collection without exposing the collection's internal structure.

**Core Idea**: Traverse a collection without knowing how it's implemented

Think of **TV remote**:
- Channel up/down buttons
- Don't need to know how channels are stored
- Just navigate next/previous
- Works with any TV brand

## Problem It Solves

**Without Iterator**:
```javascript
Different collections, different traversal methods:

// Array traversal
for (i = 0; i < array.length; i++) {
    element = array[i];
}

// Linked list traversal
node = list.head;
while (node != null) {
    element = node.data;
    node = node.next;
}

// Tree traversal
traverseInOrder(tree.root);

// Client must know internal structure
```text

**With Iterator**:
```javascript
Uniform traversal for all collections:

iterator = collection.createIterator();
while (iterator.hasNext()) {
    element = iterator.next();
}

// Same code works for any collection
// Internal structure hidden
```text

## When to Use Iterator

**Use When**:
- Need to traverse collection without exposing structure
- Want uniform interface for different collections
- Support multiple traversals simultaneously
- Need different traversal algorithms
- Want to hide collection complexity

**Don't Use When**:
- Simple array with index access is sufficient
- Collection is simple and won't change
- Direct access is clearer
- Adds unnecessary abstraction

## Structure
```text
┌──────────────────┐
│    Iterator      │ (Interface)
├──────────────────┤
│ + hasNext(): bool│
│ + next(): Element│
└────────△─────────┘
         │
         │ implements
         │
┌────────┴─────────┐
│ ConcreteIterator │
├──────────────────┤
│ - collection     │
│ - currentPosition│
├──────────────────┤
│ + hasNext()      │
│ + next()         │
└──────────────────┘

┌──────────────────┐
│   Collection     │ (Interface)
├──────────────────┤
│ + createIterator()│
└────────△─────────┘
         │
         │ implements
         │
┌────────┴─────────┐
│ConcreteCollection│
├──────────────────┤
│ - items[]        │
├──────────────────┤
│ + createIterator()│
└──────────────────┘
```

## Key Components
```text
┌────────────────────────────────────────────────────┐
│        Iterator Pattern Components                  │
└────────────────────────────────────────────────────┘

Iterator Interface
└─ hasNext(): Check if more elements exist
└─ next(): Get next element

Concrete Iterator
└─ Implements traversal algorithm
└─ Keeps track of current position

Collection Interface
└─ createIterator(): Returns iterator

Concrete Collection
└─ Stores elements
└─ Creates appropriate iterator
```javascript

## Real-World Examples

### 1. Playlist Navigation
```javascript
Playlist Collection:
├─ Songs stored in array/list
└─ createIterator() → PlaylistIterator

PlaylistIterator:
├─ hasNext() → check if more songs
├─ next() → get next song
├─ previous() → get previous song
└─ current() → get current song

Usage:
iterator = playlist.createIterator();
while (iterator.hasNext()) {
    song = iterator.next();
    playSong(song);
}

// Don't need to know how songs are stored
```sql

### 2. Social Media Feed
```javascript
Feed Collection:
├─ Posts stored in database/cache
└─ createIterator() → FeedIterator

FeedIterator:
├─ hasNext() → check if more posts
├─ next() → fetch next batch of posts
└─ Uses pagination internally

Usage:
iterator = feed.createIterator();
while (iterator.hasNext()) {
    posts = iterator.next();
    displayPosts(posts);
}

// Handles pagination transparently
```javascript

### 3. File System
```javascript
Directory Collection:
├─ Files and subdirectories
└─ createIterator() → FileIterator

FileIterator:
├─ hasNext() → more files/folders
├─ next() → get next item
└─ Can traverse depth-first or breadth-first

Usage:
iterator = directory.createIterator();
while (iterator.hasNext()) {
    file = iterator.next();
    processFile(file);
}

// Traversal method hidden from client
```

### 4. Menu System
```javascript
Menu Collection:
├─ Menu items in tree structure
└─ createIterator() → MenuIterator

MenuIterator:
├─ hasNext() → check for more items
├─ next() → get next menu item
└─ Traverses hierarchical menu

Usage:
iterator = menu.createIterator();
while (iterator.hasNext()) {
    item = iterator.next();
    renderMenuItem(item);
}

// Hierarchy traversal handled internally
```javascript

### 5. Shopping Cart
```javascript
Cart Collection:
├─ Items in cart
└─ createIterator() → CartIterator

CartIterator:
├─ hasNext() → more items in cart
├─ next() → get next item
└─ Can filter by category

Usage:
iterator = cart.createIterator();
while (iterator.hasNext()) {
    item = iterator.next();
    calculateItemTotal(item);
}
```sql

## Benefits

**Encapsulation**: Hides collection's internal structure

**Single Responsibility**: Traversal logic separate from collection

**Uniform Interface**: Same way to traverse different collections

**Multiple Traversals**: Support multiple iterators on same collection

**Flexibility**: Easy to add new traversal algorithms

**Clean Code**: No need to expose collection internals

## Drawbacks

**Overhead**: Extra objects and method calls

**Complexity**: More classes to maintain

**Simple Cases**: Overkill for simple arrays

**Modification Issues**: Problems if collection changes during iteration

## Iterator Types

### 1. External Iterator
```javascript
Client controls iteration:

iterator = collection.createIterator();
while (iterator.hasNext()) {
    element = iterator.next();
    // Client controls when to advance
}

More flexible
Client has full control
```javascript

### 2. Internal Iterator
```javascript
Collection controls iteration:

collection.forEach(function(element) {
    // Process element
});

Simpler for client
Less flexible
Collection controls flow
```

### 3. Bidirectional Iterator
```javascript
Can traverse forward and backward:

iterator.next();      // Move forward
iterator.previous();  // Move backward
iterator.hasNext();   // Check forward
iterator.hasPrevious(); // Check backward

Useful for playlists, history
```text

### 4. Filtered Iterator
```javascript
Returns only elements matching criteria:

iterator = collection.createIterator(filter);
// Only returns elements passing filter

Combines iteration with filtering
```sql

## Iterator Pattern Flow
```text
┌────────────────────────────────────────────────────┐
│            Iterator Pattern Flow                    │
└────────────────────────────────────────────────────┘

Step 1: Client requests iterator from collection
    ↓
Step 2: Collection creates and returns iterator
    ↓
Step 3: Client calls hasNext() to check availability
    ↓
Step 4: If hasNext() is true, client calls next()
    ↓
Step 5: Iterator returns element and advances position
    ↓
Step 6: Repeat steps 3-5 until hasNext() is false
```text

## Common Iterator Methods
```text
┌────────────────────────────────────────────────────┐
│           Common Iterator Methods                   │
└────────────────────────────────────────────────────┘

hasNext(): boolean
└─ Returns true if more elements exist

next(): Element
└─ Returns next element and advances

hasPrevious(): boolean
└─ Returns true if previous elements exist

previous(): Element
└─ Returns previous element and moves back

reset(): void
└─ Resets iterator to beginning

current(): Element
└─ Returns current element without advancing

remove(): void
└─ Removes current element from collection
```

## Implementation Considerations

### Concurrent Modification
```text
Problem:
└─ Collection modified while iterating

Solutions:
├─ Fail-fast: Throw error if collection modified
├─ Snapshot: Iterator works on collection copy
└─ Weak consistency: May or may not see modifications
```text

### Lazy Evaluation
```javascript
Don't load all elements upfront:

iterator.next() {
    // Load element only when requested
    // Useful for large collections or databases
}

Benefits:
├─ Saves memory
├─ Better performance
└─ Works with infinite collections
```text

### Null Handling
```javascript
What to return when no more elements?

Options:
├─ Return null (check hasNext() first)
├─ Throw exception
└─ Return Optional/Maybe type
```

## Real-World Use Cases
```text
┌────────────────────────────────────────────────────┐
│      Common Iterator Pattern Applications           │
└────────────────────────────────────────────────────┘

Collections Frameworks
└─ Arrays, Lists, Sets, Maps

Database Result Sets
└─ Iterate over query results

File Systems
└─ Navigate directories and files

Graph Traversal
└─ BFS, DFS algorithms

Pagination
└─ Web APIs, search results

Composite Structures
└─ Trees, hierarchies

Streams
└─ Data streams, event streams

Social Feeds
└─ Infinite scrolling feeds
```text

## Iterator vs For-Each Loop
```text
┌────────────────────────────────────────────────────┐
│         Iterator vs For-Each Loop                   │
└────────────────────────────────────────────────────┘

Iterator                      For-Each
├─ Explicit control           ├─ Implicit iteration
├─ Can remove elements        ├─ Cannot remove during loop
├─ More verbose               ├─ More concise
├─ Full control               ├─ Simplified syntax
└─ Works with any collection  └─ Requires iterable collection

For-Each often uses Iterator internally
```text

## Best Practices

**Fail-Fast**: Detect concurrent modifications early

**Consistent State**: Ensure iterator state is always valid

**Resource Cleanup**: Close resources when iteration complete

**Null Safety**: Handle null elements gracefully

**Document Behavior**: Clearly document thread-safety, modification rules

**Immutability**: Consider making iterators immutable

**Interface Segregation**: Only include necessary methods

## Advanced Patterns

### Composite Iterator
```text
Iterates over composite structures:

TreeIterator traverses tree
├─ Can use different strategies
├─ Depth-first
├─ Breadth-first
└─ Pre-order, in-order, post-order
```

### Filtering Iterator
```text
Wraps another iterator with filter:

FilteredIterator:
└─ next() skips elements not matching filter
└─ hasNext() finds next matching element
```text

### Chained Iterators
```text
Combines multiple iterators:

ChainedIterator:
└─ Iterates first collection
└─ Then second collection
└─ Seamless to client
```

## Pros and Cons Summary
```text
✅ Pros
├─ Hides internal structure
├─ Uniform traversal interface
├─ Multiple simultaneous iterations
├─ Different traversal algorithms
├─ Single Responsibility Principle
└─ Open/Closed Principle

❌ Cons
├─ Overkill for simple collections
├─ Extra classes and complexity
├─ Performance overhead
├─ Concurrent modification issues
└─ May need multiple iterator types
```

## When to Use Iterator Pattern

**Use When**:
- Collection structure is complex or may change
- Need uniform way to traverse different collections
- Want to hide implementation details
- Need multiple simultaneous traversals
- Traversal logic is complex

**Don't Use When**:
- Simple array with index access
- Collection structure is trivial
- Direct access is clearer
- Performance is critical
- Only one way to traverse

## Key Takeaways

- **Provides sequential access** without exposing structure
- **Uniform interface** for different collections
- **Separates traversal logic** from collection
- **Supports multiple iterations** simultaneously
- **Hides implementation details** from client
- **Use when**: Complex collections need traversal
- **Don't use when**: Simple collections with direct access

**Remember**: Iterator pattern is about providing a standard way to traverse a collection without knowing how it's implemented internally. Modern languages often have built-in iterator support, but understanding the pattern helps you use them effectively.

---

# Observer Pattern

The Observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

## What is Observer Pattern?

**Observer Pattern**: Notifies multiple objects automatically when another object's state changes.

**Core Idea**: Subscribe to events and get notified when they happen

Think of **YouTube subscriptions**:
- YouTuber (Subject) uploads video
- Subscribers (Observers) get notified
- More subscribers = more notifications sent
- Can subscribe/unsubscribe anytime

## Problem It Solves

**Without Observer**:
```javascript
Manual notification of changes:

// Weather station updates
weatherStation.updateTemperature(25);

// Must manually notify all displays
display1.update(weatherStation);
display2.update(weatherStation);
display3.update(weatherStation);

// Easy to forget to notify someone
// Tight coupling between station and displays
```text

**With Observer**:
```javascript
Automatic notification:

weatherStation.updateTemperature(25);
// Automatically notifies all registered observers

display1 subscribes to weatherStation
display2 subscribes to weatherStation
display3 subscribes to weatherStation

// All displays notified automatically
// Loose coupling
```

## When to Use Observer

**Use When**:
- One object's change affects many others
- Don't know how many objects need notification
- Want loose coupling between objects
- Need dynamic subscription/unsubscription
- Implementing event handling systems

**Don't Use When**:
- Simple one-to-one relationships
- Notification order matters critically
- Performance is critical (many observers)
- Can lead to memory leaks if not careful

## Structure
```text
┌──────────────┐
│   Subject    │ (Interface)
├──────────────┤
│ + attach()   │
│ + detach()   │
│ + notify()   │
└──────△───────┘
       │
       │ implements
       │
┌──────┴───────┐
│Concrete      │
│Subject       │
├──────────────┤           ┌──────────────┐
│ - observers  │───────────│  Observer    │ (Interface)
│ - state      │    *      ├──────────────┤
├──────────────┤           │ + update()   │
│ + getState() │           └──────△───────┘
│ + setState() │                  │
└──────────────┘                  │ implements
                                  │
                          ┌───────┴────────┐
                          │                │
                   ┌──────┴─────┐   ┌──────┴─────┐
                   │ConcreteA   │   │ConcreteB   │
                   │Observer    │   │Observer    │
                   ├────────────┤   ├────────────┤
                   │ + update() │   │ + update() │
                   └────────────┘   └────────────┘
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│        Observer Pattern Components                  │
└────────────────────────────────────────────────────┘

Subject
└─ Maintains list of observers
└─ Provides methods to attach/detach observers
└─ Notifies observers of state changes

Observer
└─ Interface for objects that should be notified
└─ Defines update method

Concrete Subject
└─ Stores state of interest
└─ Sends notification when state changes

Concrete Observer
└─ Maintains reference to subject
└─ Implements update to stay synchronized
```sql

## Real-World Examples

### 1. Weather Station
```text
WeatherStation (Subject):
├─ temperature, humidity, pressure
├─ attach(observer)
├─ detach(observer)
└─ notifyObservers()

Observers:
├─ PhoneDisplay
│   └─ update() → show on phone
├─ TVDisplay
│   └─ update() → show on TV
└─ WebsiteDisplay
    └─ update() → update website

Flow:
weatherStation.setTemperature(25);
└─> notifies all displays
    └─> each display updates itself
```

### 2. Stock Market
```text
Stock (Subject):
├─ price
├─ attach(observer)
└─ notifyObservers()

Observers:
├─ Investor
│   └─ update() → check portfolio
├─ TradingBot
│   └─ update() → execute trades
└─ PriceDisplay
    └─ update() → update UI

When price changes:
stock.setPrice(150.50);
└─> all observers notified
    └─> investors alerted
    └─> bots may trade
    └─> displays updated
```text

### 3. Newsletter Subscription
```javascript
Newsletter (Subject):
├─ subscribers list
├─ subscribe(email)
├─ unsubscribe(email)
└─ notifySubscribers()

Subscribers (Observers):
├─ EmailSubscriber
│   └─ update() → send email
├─ SMSSubscriber
│   └─ update() → send SMS
└─ AppNotificationSubscriber
    └─ update() → push notification

When new article published:
newsletter.publish(article);
└─> all subscribers notified
```javascript

### 4. Social Media
```javascript
User (Subject):
├─ followers list
├─ addFollower(user)
├─ removeFollower(user)
└─ notifyFollowers()

Followers (Observers):
└─ update() → see new post in feed

When user posts:
user.createPost("Hello!");
└─> all followers get notification
    └─> appears in their feeds
```

### 5. Event Management System
```text
EventManager (Subject):
├─ listeners for different events
├─ subscribe(eventType, listener)
├─ unsubscribe(eventType, listener)
└─ notify(eventType, data)

Listeners (Observers):
├─ LoggingListener
│   └─ update() → log event
├─ AnalyticsListener
│   └─ update() → track metrics
└─ NotificationListener
    └─ update() → send notifications

When event occurs:
eventManager.notify("userLogin", userData);
└─> all relevant listeners notified
```sql

## Observer Pattern Flow
```javascript
┌────────────────────────────────────────────────────┐
│            Observer Pattern Flow                    │
└────────────────────────────────────────────────────┘

Step 1: Observers register with subject
    observer.attach(subject)
    ↓
Step 2: Subject stores observer references
    observers.add(observer)
    ↓
Step 3: Subject state changes
    subject.setState(newState)
    ↓
Step 4: Subject notifies all observers
    for each observer: observer.update()
    ↓
Step 5: Observers pull/receive new state
    newState = subject.getState()
    ↓
Step 6: Observers update themselves
    display.refresh()
```javascript

## Push vs Pull Model

### Push Model
```javascript
Subject pushes data to observers:

notify(data) {
    for (observer in observers) {
        observer.update(data);  // Push data
    }
}

Observer receives data directly
└─ Less coupling to subject
└─ May receive unwanted data
```

### Pull Model
```javascript
Subject just notifies, observers pull data:

notify() {
    for (observer in observers) {
        observer.update();  // No data passed
    }
}

Observer pulls needed data:
update() {
    data = subject.getState();  // Pull data
}

└─ Observer decides what to get
└─ More coupling to subject
└─ More flexible for observer
```javascript

## Benefits

**Loose Coupling**: Subject and observers are loosely coupled

**Dynamic Relationships**: Add/remove observers at runtime

**Broadcast Communication**: One change notifies many

**Open/Closed Principle**: Add new observers without modifying subject

**Flexibility**: Observers can subscribe to multiple subjects

## Drawbacks

**Memory Leaks**: Observers not unsubscribed can cause leaks

**Unexpected Updates**: Hard to track who gets notified

**Order Issues**: Notification order may matter but isn't guaranteed

**Performance**: Many observers can slow down notifications

**Debugging**: Hard to trace notification chains

## Notification Strategies

### 1. Immediate Notification
```javascript
State changes → immediate notification

setState(value) {
    this.state = value;
    this.notifyObservers();  // Notify immediately
}

Pros: Simple, real-time updates
Cons: Can be inefficient with frequent changes
```javascript

### 2. Batch Notification
```javascript
Collect changes, notify once:

setState(value) {
    this.state = value;
    this.dirty = true;
}

commit() {
    if (this.dirty) {
        this.notifyObservers();
        this.dirty = false;
    }
}

Pros: Efficient for multiple changes
Cons: Delayed updates
```javascript

### 3. Filtered Notification
```javascript
Notify only interested observers:

notify(eventType) {
    observers = this.getObservers(eventType);
    for (observer in observers) {
        observer.update(eventType);
    }
}

Only relevant observers notified
```

## Common Variations

### 1. Event-Driven Observer
```text
Subject emits named events:

subject.on('update', callback);
subject.emit('update', data);

Common in JavaScript/Node.js
```text

### 2. Multicast Delegate
```text
Subject maintains list of callbacks:

subject.addListener(callback);
subject.notifyListeners();

Function-based instead of object-based
```

### 3. Reactive Programming
```text
Modern variation using streams:

observable.subscribe(
    onNext,
    onError,
    onComplete
);

Examples: RxJS, Reactive Extensions
```text

## Real-World Use Cases
```text
┌────────────────────────────────────────────────────┐
│      Common Observer Pattern Applications           │
└────────────────────────────────────────────────────┘

Event Systems
└─ GUI events, button clicks, keyboard input

Model-View Architecture
└─ MVC, MVVM patterns

Real-time Updates
└─ Stock prices, sports scores, weather

Social Media
└─ Followers, notifications, feeds

Monitoring Systems
└─ Server monitoring, alerts

Data Binding
└─ UI frameworks, form validation

Publish-Subscribe Systems
└─ Message queues, event buses

IoT Systems
└─ Sensor networks, smart home devices
```text

## Observer vs Pub/Sub Pattern
```text
┌────────────────────────────────────────────────────┐
│         Observer vs Publish-Subscribe               │
└────────────────────────────────────────────────────┘

Observer                      Pub/Sub
├─ Direct relationship        ├─ Message broker/event bus
├─ Observers know subject     ├─ Publishers don't know subscribers
├─ Tightly coupled           ├─ Loosely coupled
├─ Synchronous typically     ├─ Asynchronous typically
├─ Same process              ├─ Can be distributed
└─ Simple, direct            └─ More complex, flexible

Pub/Sub is evolution of Observer for distributed systems
```javascript

## Memory Management

### Preventing Memory Leaks
```javascript
Problem: Observer not detached

observer = new DisplayObserver();
subject.attach(observer);
// observer goes out of scope but still attached
// Memory leak!

Solution: Always detach

observer = new DisplayObserver();
subject.attach(observer);
// ... use observer ...
subject.detach(observer);  // Clean up
```

### Weak References
```javascript
Use weak references for observers:

observers = new WeakSet();
// Observers can be garbage collected
// Even if still in observers set
```javascript

## Best Practices

**Always Detach**: Remove observers when no longer needed

**Avoid Cycles**: Be careful of circular dependencies

**Thread Safety**: Use synchronization if multithreaded

**Specific Notifications**: Use event types to filter notifications

**Document**: Clearly document notification timing and order

**Error Handling**: Handle observer errors gracefully

**Performance**: Consider async notifications for many observers

## Implementation Considerations

### Error Handling
```javascript
notify() {
    for (observer in observers) {
        try {
            observer.update();
        } catch (error) {
            // Log error but continue notifying others
            console.error(error);
        }
    }
}

One observer's error shouldn't break others
```text

### Notification Order
```text
Options:
├─ Insertion order (simple)
├─ Priority queue (controlled order)
└─ Random order (no guarantees)

Document which approach you use
```

### Update Granularity
```text
Fine-grained:
└─ Separate update for each property change
└─ More notifications, more specific

Coarse-grained:
└─ Single update for multiple changes
└─ Fewer notifications, batch updates
```text

## Pros and Cons Summary
```
✅ Pros
├─ Loose coupling between subject and observers
├─ Dynamic subscription/unsubscription
├─ Broadcast communication
├─ Open/Closed Principle
├─ Runtime relationships
└─ Event-driven architecture support

❌ Cons
├─ Memory leak risk
├─ Unexpected updates
├─ Notification order uncertainty
├─ Performance with many observers
├─ Debugging difficulty
└─ Observer management complexity
```sql

## When to Use Observer Pattern

**Use When**:
- One object's changes affect multiple objects
- Number of dependents is unknown or changes
- Need loose coupling between objects
- Implementing event systems
- Broadcasting changes to many objects

**Don't Use When**:
- Simple one-to-one relationships
- Notification order is critical
- Performance overhead is unacceptable
- Synchronous updates are required
- Can use simpler callback mechanisms

## Key Takeaways

- **One-to-many dependency** between objects
- **Automatic notification** when state changes
- **Dynamic subscription** and unsubscription
- **Loose coupling** between subject and observers
- **Foundation** for event-driven systems
- **Use when**: Changes need to trigger multiple updates
- **Don't use when**: Simple direct calls are sufficient

**Remember**: Observer pattern is about automatic notification of state changes to multiple interested parties. It's the foundation of event-driven programming and reactive systems. Be careful with memory management and notification order.

---

# Command Pattern

The Command pattern encapsulates a request as an object, allowing you to parameterize clients with different requests, queue requests, log requests, and support undoable operations.

## What is Command Pattern?

**Command Pattern**: Turns a request into a stand-alone object that contains all information about the request.

**Core Idea**: Package actions as objects

Think of a **restaurant order**:
- Waiter takes order (doesn't cook)
- Order slip contains all details
- Chef executes order
- Order can be queued, modified, or cancelled

## Problem It Solves

**Without Command**:
```javascript
Direct method calls everywhere:

button.onClick = turnOnLight;
// Tight coupling
// Can't undo, queue, or log
// Can't parameterize actions
```javascript

**With Command**:
```javascript
Actions as objects:

turnOnCommand = new TurnOnLightCommand(light);
button.setCommand(turnOnCommand);
button.press();  // Executes command

// Can undo, queue, log commands
// Decoupled from receiver
```

## When to Use Command

**Use When**:
- Need undo/redo functionality
- Want to queue or schedule operations
- Need to log operations
- Want to parameterize objects with actions
- Need to support transactions

**Don't Use When**:
- Simple direct method calls work fine
- Don't need undo or queuing
- Adds unnecessary complexity

## Structure
```text
┌──────────────┐
│   Invoker    │
├──────────────┤
│ - command    │
├──────────────┤
│ + setCommand()│
│ + execute()  │
└──────┬───────┘
       │ uses
       ▼
┌──────────────┐
│   Command    │ (Interface)
├──────────────┤
│ + execute()  │
│ + undo()     │
└──────△───────┘
       │
       │ implements
       │
┌──────┴───────┐
│Concrete      │
│Command       │
├──────────────┤
│ - receiver   │──────┐
├──────────────┤      │
│ + execute()  │      │ calls
│ + undo()     │      │
└──────────────┘      │
                      ▼
               ┌──────────────┐
               │   Receiver   │
               ├──────────────┤
               │ + action()   │
               └──────────────┘
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│        Command Pattern Components                   │
└────────────────────────────────────────────────────┘

Command Interface
└─ execute(): Perform action
└─ undo(): Reverse action

Concrete Command
└─ Holds reference to receiver
└─ Implements execute() and undo()

Receiver
└─ Knows how to perform actual work

Invoker
└─ Asks command to execute
└─ Doesn't know about receiver

Client
└─ Creates command and sets receiver
```sql

## Real-World Examples

### 1. Text Editor (Undo/Redo)
```text
Commands:
├─ TypeCommand(text)
│   ├─ execute() → add text
│   └─ undo() → remove text
├─ DeleteCommand(position, length)
│   ├─ execute() → delete text
│   └─ undo() → restore deleted text
└─ FormatCommand(style)
    ├─ execute() → apply formatting
    └─ undo() → remove formatting

Editor keeps command history
Can undo/redo any operation
```

### 2. Remote Control
```text
Commands:
├─ TurnOnCommand(device)
├─ TurnOffCommand(device)
├─ VolumeUpCommand(device)
└─ VolumeDownCommand(device)

Remote control (Invoker):
└─ button1.setCommand(turnOnTV)
└─ button2.setCommand(volumeUp)
└─ button3.setCommand(turnOffTV)

Each button executes its command
Can reconfigure buttons easily
```

### 3. Transaction System
```text
Commands:
├─ DebitCommand(account, amount)
├─ CreditCommand(account, amount)
└─ TransferCommand(from, to, amount)

Transaction manager:
└─ Executes commands
└─ Logs all operations
└─ Can rollback on failure

Supports atomic transactions
```

### 4. Task Scheduler
```text
Commands:
├─ SendEmailCommand(recipient, message)
├─ BackupCommand(database)
└─ ReportCommand(type)

Scheduler:
└─ Queue commands
└─ Execute at scheduled time
└─ Retry on failure

Commands can be saved and loaded
```

### 5. Smart Home
```text
Commands:
├─ TurnOnLightsCommand(room)
├─ AdjustTemperatureCommand(temp)
├─ LockDoorsCommand()
└─ PlayMusicCommand(playlist)

Macro command:
└─ "Good Morning" macro
    ├─ Turn on lights
    ├─ Adjust temperature
    └─ Play music

Execute multiple commands as one
```

## Benefits

**Decoupling**: Separates invoker from receiver

**Undo/Redo**: Easy to implement reversible operations

**Queuing**: Commands can be queued and scheduled

**Logging**: Record operations for audit trail

**Macro Commands**: Combine multiple commands

**Extensibility**: Add new commands without changing existing code

## Drawbacks

**Complexity**: Many small command classes

**Overhead**: Extra objects for each operation

**Memory**: Command history consumes memory

## Command Pattern Flow
```javascript
┌────────────────────────────────────────────────────┐
│            Command Pattern Flow                     │
└────────────────────────────────────────────────────┘

Step 1: Client creates command
    command = new ConcreteCommand(receiver)
    ↓
Step 2: Client sets command on invoker
    invoker.setCommand(command)
    ↓
Step 3: Invoker calls execute
    invoker.execute()
    ↓
Step 4: Command calls receiver's action
    receiver.action()
    ↓
Step 5: For undo, invoker calls undo
    invoker.undo()
    ↓
Step 6: Command reverses the action
    receiver.reverseAction()
```text

## Undo/Redo Implementation
```text
Command history stack:

History: [Command1, Command2, Command3]
                                  ↑
                              current

Undo:
└─ Execute undo on current command
└─ Move current pointer back
└─ History: [Command1, Command2, Command3]
                          ↑
                      current

Redo:
└─ Move current pointer forward
└─ Execute command
└─ History: [Command1, Command2, Command3]
                                  ↑
                              current
```text

## Macro Commands
```text
Composite command containing multiple commands:

MacroCommand:
├─ commands: [Command1, Command2, Command3]
├─ execute() {
│     for each command: command.execute()
│   }
└─ undo() {
      for each command (reverse): command.undo()
  }

Example: "Save All" command
└─ Combines multiple save commands
```text

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│      Common Command Pattern Applications            │
└────────────────────────────────────────────────────┘

Text Editors
└─ Undo/redo operations

GUI Applications
└─ Button actions, menu items

Database Transactions
└─ Atomic operations, rollback

Job Schedulers
└─ Queue and execute tasks

Game Development
└─ Player actions, replays

Home Automation
└─ Device control, macros

Workflow Systems
└─ Process steps, rollback

Network Protocols
└─ Request/response handling
```

## Best Practices

**Immutable Commands**: Make commands immutable once created

**Small Commands**: Each command does one thing

**Store State**: Save state needed for undo

**Clear Naming**: Use descriptive command names (SaveDocumentCommand)

**Error Handling**: Handle failures gracefully

**Command History Limit**: Limit undo stack size

**Logging**: Log command execution for debugging

## Pros and Cons Summary
```text
✅ Pros
├─ Decouples sender and receiver
├─ Easy undo/redo implementation
├─ Supports queuing and logging
├─ Macro commands possible
├─ Open/Closed Principle
└─ Single Responsibility Principle

❌ Cons
├─ Many command classes
├─ Additional complexity
├─ Memory overhead
└─ May be overkill for simple cases
```

## Key Takeaways

- **Encapsulates requests** as objects
- **Enables undo/redo** functionality
- **Supports queuing** and logging
- **Decouples invoker** from receiver
- **Allows macro commands** (composite)
- **Use when**: Need undo, queuing, or logging
- **Don't use when**: Simple method calls are sufficient

**Remember**: Command pattern is about turning actions into objects. It's essential for implementing undo/redo, queuing operations, and creating flexible, decoupled systems where actions can be parameterized, logged, and reversed.

---
# State Pattern

The State pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class.

## What is State Pattern?

**State Pattern**: Changes object behavior based on its internal state.

**Core Idea**: Different behavior for different states

Think of a **vending machine**:
- Idle state: Waiting for money
- Has money state: Waiting for selection
- Dispensing state: Giving product
- Out of stock state: Rejecting requests
- Same machine, different behaviors per state

## Problem It Solves

**Without State**:
```javascript
Conditional logic for every state:

function pressButton() {
    if (state === 'idle') {
        // Idle behavior
    } else if (state === 'hasMoney') {
        // Has money behavior
    } else if (state === 'dispensing') {
        // Dispensing behavior
    } else if (state === 'outOfStock') {
        // Out of stock behavior
    }
}

// Complex, hard to maintain
// Violates Open/Closed Principle
```javascript

**With State**:
```javascript
Each state is a separate class:

context.setState(new IdleState());
context.pressButton();  // Delegates to current state

// Easy to add new states
// Clean, maintainable code
```text

## When to Use State

**Use When**:
- Object behavior depends on its state
- Many conditional statements based on state
- States have complex behaviors
- State transitions are well-defined

**Don't Use When**:
- Few states with simple behavior
- State transitions are rare
- Adds unnecessary complexity

## Structure
```text
┌──────────────┐
│   Context    │
├──────────────┤
│ - state      │
├──────────────┤
│ + setState() │
│ + request()  │
└──────┬───────┘
       │ delegates to
       ▼
┌──────────────┐
│    State     │ (Interface)
├──────────────┤
│ + handle()   │
└──────△───────┘
       │
   ┌───┴────────┬─────────┐
   │            │         │
┌──┴──────┐ ┌──┴──────┐ ┌┴────────┐
│StateA   │ │StateB   │ │StateC   │
├─────────┤ ├─────────┤ ├─────────┤
│+handle()│ │+handle()│ │+handle()│
└─────────┘ └─────────┘ └─────────┘
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│         State Pattern Components                    │
└────────────────────────────────────────────────────┘

State Interface
└─ Defines methods for handling requests

Concrete States
└─ Implement behavior for specific state
└─ May trigger state transitions

Context
└─ Maintains current state
└─ Delegates requests to current state
```

## Real-World Examples

### 1. Document States
```text
States:
├─ Draft
│   ├─ edit() → allowed
│   ├─ publish() → moves to Moderation
│   └─ delete() → allowed
├─ Moderation
│   ├─ edit() → not allowed
│   ├─ approve() → moves to Published
│   └─ reject() → moves to Draft
└─ Published
    ├─ edit() → not allowed
    ├─ unpublish() → moves to Draft
    └─ delete() → not allowed

Each state has different allowed operations
```text

### 2. TCP Connection
```text
States:
├─ Closed
│   └─ open() → moves to Listen
├─ Listen
│   └─ connect() → moves to Established
├─ Established
│   ├─ send() → allowed
│   ├─ receive() → allowed
│   └─ close() → moves to Closed
└─ Closing
    └─ timeout() → moves to Closed

Network connection behaves differently per state
```

### 3. Order Processing
```text
States:
├─ New
│   ├─ pay() → moves to Paid
│   └─ cancel() → moves to Cancelled
├─ Paid
│   ├─ ship() → moves to Shipped
│   └─ refund() → moves to Refunded
├─ Shipped
│   └─ deliver() → moves to Delivered
└─ Delivered
    └─ return() → moves to Returned

Order goes through defined lifecycle
```text

### 4. Audio Player
```text
States:
├─ StoppedState
│   └─ play() → moves to Playing
├─ PlayingState
│   ├─ pause() → moves to Paused
│   └─ stop() → moves to Stopped
└─ PausedState
    ├─ play() → moves to Playing
    └─ stop() → moves to Stopped

Player behavior changes with state
```

### 5. Traffic Light
```text
States:
├─ RedLight
│   └─ next() → moves to Green
│   └─ canGo() → returns false
├─ YellowLight
│   └─ next() → moves to Red
│   └─ canGo() → returns false
└─ GreenLight
    └─ next() → moves to Yellow
    └─ canGo() → returns true

Each light has different rules
```javascript

## Benefits

**Eliminates Conditionals**: No if-else for state checks

**Single Responsibility**: Each state class handles one state

**Open/Closed**: Add new states without modifying existing code

**Clarity**: State-specific behavior is localized

**State Transitions**: Clear, explicit state changes

## Drawbacks

**Complexity**: Many state classes

**Overhead**: More objects created

**State Management**: Must manage state transitions carefully

**Overkill**: Too complex for simple state machines

## State Pattern Flow
```javascript
┌────────────────────────────────────────────────────┐
│             State Pattern Flow                      │
└────────────────────────────────────────────────────┘

Step 1: Context created with initial state
    context = new Context(new StateA())
    ↓
Step 2: Client calls method on context
    context.request()
    ↓
Step 3: Context delegates to current state
    state.handle(context)
    ↓
Step 4: State executes behavior
    // State-specific logic
    ↓
Step 5: State may transition to new state
    context.setState(new StateB())
    ↓
Step 6: Next request uses new state
    context.request()  // Uses StateB now
```javascript

## State Transitions

### Option 1: States Control Transitions
```javascript
State decides when to transition:

class PlayingState {
    pause(context) {
        // Do pause actions
        context.setState(new PausedState());
    }
}

Pros: State knows its transitions
Cons: States know about other states
```

### Option 2: Context Controls Transitions
```javascript
Context decides transitions:

class Context {
    play() {
        this.state.play();
        if (shouldPause) {
            this.setState(new PausedState());
        }
    }
}

Pros: Centralized transition logic
Cons: Context knows all states
```text

## State vs Strategy Pattern
```javascript
┌────────────────────────────────────────────────────┐
│          State vs Strategy Pattern                  │
└────────────────────────────────────────────────────┘

State                         Strategy
├─ Changes behavior by state  ├─ Changes algorithm
├─ State transitions occur    ├─ Strategy set by client
├─ States may know each other ├─ Strategies independent
├─ Context changes state      ├─ Client sets strategy
├─ State-dependent behavior   ├─ Interchangeable algorithms
└─ Intent: State management   └─ Intent: Algorithm choice

Similar structure, different intent
```javascript

## Implementation Variations

### 1. Simple State Machine
```javascript
Basic state with transitions:

class State {
    handle(context) {
        // Perform action
        context.setState(nextState);
    }
}
```text

### 2. Hierarchical States
```
States can have substates:

AbstractState
├─ OnState
│   ├─ PlayingState
│   └─ PausedState
└─ OffState
```javascript

### 3. State with Data
```javascript
States can maintain data:

class State {
    constructor() {
        this.data = {};
    }
    
    handle(context) {
        // Use state-specific data
    }
}
```text

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│       Common State Pattern Applications             │
└────────────────────────────────────────────────────┘

Workflow Systems
└─ Document approval, order processing

UI Components
└─ Buttons, forms with different states

Game Characters
└─ Idle, walking, jumping, attacking states

Network Protocols
└─ Connection states (TCP, HTTP)

Vending Machines
└─ Idle, accepting money, dispensing

Media Players
└─ Playing, paused, stopped states

Authentication
└─ Logged in, logged out, session expired

Parsers
└─ Different parsing states
```text

## Best Practices

**Clear States**: Define states clearly and explicitly

**State Transitions**: Document all valid transitions

**Single Entry/Exit**: Define entry and exit actions

**Immutable States**: Make state objects immutable

**Singleton States**: Reuse state instances if stateless

**Validation**: Validate state transitions

**Logging**: Log state changes for debugging

## Example: Vending Machine
```javascript
States and behaviors:

IdleState:
└─ insertMoney() → moves to HasMoneyState
└─ selectProduct() → error (no money)
└─ dispense() → error (no selection)

HasMoneyState:
└─ insertMoney() → add to total
└─ selectProduct() → moves to DispensingState
└─ cancel() → return money, moves to IdleState

DispensingState:
└─ dispense() → give product, moves to IdleState
└─ Other actions → not allowed

OutOfStockState:
└─ All actions → error message
```

## Pros and Cons Summary
```javascript
✅ Pros
├─ Eliminates complex conditionals
├─ Each state in separate class
├─ Easy to add new states
├─ Clear state transitions
├─ Single Responsibility Principle
└─ Open/Closed Principle

❌ Cons
├─ Many state classes
├─ Overhead for simple cases
├─ State transition management
└─ May be overkill
```javascript

## Key Takeaways

- **Changes behavior** based on internal state
- **Each state** is a separate class
- **Eliminates** complex conditional logic
- **Clear state transitions** and behaviors
- **Context delegates** to current state
- **Use when**: Object has distinct states with different behaviors
- **Don't use when**: Simple state with few transitions

**Remember**: State pattern is about having an object change its behavior when its state changes. It's like the object changing its class. Use it when you have clear, distinct states with different behaviors, not just for simple boolean flags.

---

# Template Method Pattern

The Template Method pattern defines the skeleton of an algorithm in a base class but lets subclasses override specific steps of the algorithm without changing its structure.

## What is Template Method Pattern?

**Template Method Pattern**: Defines algorithm structure in base class, subclasses implement specific steps.

**Core Idea**: Algorithm skeleton is fixed, specific steps vary

Think of a **recipe**:
- Steps are the same: prepare, cook, serve
- Each dish implements steps differently
- Pasta: boil water, cook pasta, add sauce
- Pizza: prepare dough, add toppings, bake
- Same process, different implementations

## Problem It Solves

**Without Template Method**:
```javascript
Duplicated algorithm structure:

class Tea {
    make() {
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }
}

class Coffee {
    make() {
        boilWater();        // Duplicated
        brewCoffee();
        pourInCup();        // Duplicated
        addSugarAndMilk();
}

// Common steps duplicated
// Hard to maintain consistency
```javascript

**With Template Method**:
```javascript
Common structure in base class:

abstract class Beverage {
    // Template method (final)
    make() {
        boilWater();    // Common
        brew();         // Varies
        pourInCup();    // Common
        addCondiments(); // Varies
    }
    
    abstract brew();
    abstract addCondiments();
}

// Structure fixed, steps vary
```text

## When to Use Template Method

**Use When**:
- Multiple classes share algorithm structure
- Want to control algorithm extension points
- Common behavior should be in one place
- Subclasses should implement specific steps only

**Don't Use When**:
- Algorithm structure varies significantly
- Need more flexibility than inheritance provides
- Composition would be simpler

## Structure
```text
┌──────────────────┐
│ AbstractClass    │
├──────────────────┤
│ + templateMethod()│ ← Defines algorithm
├──────────────────┤
│ # step1()        │ ← Common implementation
│ # step2()        │ ← Abstract (must override)
│ # step3()        │ ← Hook (can override)
└────────△─────────┘
         │
    ┌────┴────┐
    │         │
┌───┴──────┐ ┌┴────────┐
│ConcreteA │ │ConcreteB│
├──────────┤ ├─────────┤
│+ step2() │ │+ step2()│
│+ step3() │ │+ step3()│
└──────────┘ └─────────┘
```

## Key Components
```text
┌────────────────────────────────────────────────────┐
│      Template Method Pattern Components             │
└────────────────────────────────────────────────────┘

Template Method
└─ Defines algorithm skeleton
└─ Calls primitive operations
└─ Usually final/sealed

Primitive Operations
└─ Abstract methods subclasses must implement

Hook Methods
└─ Optional methods subclasses can override
└─ Default implementation in base class

Concrete Methods
└─ Common operations implemented in base class
```javascript

## Real-World Examples

### 1. Data Mining
```javascript
Abstract DataMiner:
└─ mine() {                    // Template method
      openFile();              // Common
      extractData();           // Varies
      parseData();             // Varies
      analyzeData();           // Common
      closeFile();             // Common
   }

PDFDataMiner:
└─ extractData() → extract from PDF
└─ parseData() → parse PDF format

CSVDataMiner:
└─ extractData() → extract from CSV
└─ parseData() → parse CSV format

XMLDataMiner:
└─ extractData() → extract from XML
└─ parseData() → parse XML format
```text

### 2. Game Character AI
```javascript
Abstract CharacterAI:
└─ takeTurn() {                // Template method
      assessSituation();       // Common
      selectAction();          // Varies
      executeAction();         // Varies
      updateState();           // Common
   }

AggressiveAI:
└─ selectAction() → choose attack
└─ executeAction() → perform attack

DefensiveAI:
└─ selectAction() → choose defend
└─ executeAction() → perform defense

SupportAI:
└─ selectAction() → choose heal/buff
└─ executeAction() → perform support action
```javascript

### 3. Order Processing
```javascript
Abstract OrderProcessor:
└─ processOrder() {            // Template method
      validateOrder();         // Common
      calculateTotal();        // Common
      processPayment();        // Varies
      sendConfirmation();      // Varies
      updateInventory();       // Common
   }

OnlineOrderProcessor:
└─ processPayment() → credit card
└─ sendConfirmation() → email

InStoreOrderProcessor:
└─ processPayment() → cash/card
└─ sendConfirmation() → receipt

PhoneOrderProcessor:
└─ processPayment() → card over phone
└─ sendConfirmation() → SMS
```

### 4. Report Generation
```javascript
Abstract ReportGenerator:
└─ generate() {                // Template method
      fetchData();             // Common
      formatHeader();          // Varies
      formatBody();            // Varies
      formatFooter();          // Varies
      saveReport();            // Common
   }

PDFReport:
└─ formatHeader() → PDF header
└─ formatBody() → PDF body
└─ formatFooter() → PDF footer

HTMLReport:
└─ formatHeader() → HTML header
└─ formatBody() → HTML body
└─ formatFooter() → HTML footer

ExcelReport:
└─ formatHeader() → Excel header
└─ formatBody() → Excel body
└─ formatFooter() → Excel footer
```javascript

### 5. Build Process
```javascript
Abstract Builder:
└─ build() {                   // Template method
      clean();                 // Common
      compile();               // Varies
      test();                  // Varies
      package();               // Varies
      deploy();                // Hook (optional)
   }

JavaBuilder:
└─ compile() → javac
└─ test() → JUnit
└─ package() → JAR

JavaScriptBuilder:
└─ compile() → Babel/TypeScript
└─ test() → Jest
└─ package() → webpack bundle
```javascript

## Types of Methods

### 1. Template Method
```text
Final method defining algorithm:

final void templateMethod() {
    step1();
    step2();
    step3();
}

Cannot be overridden
Calls other methods
```javascript

### 2. Abstract Operations
```javascript
Must be implemented by subclasses:

abstract void step2();

No default implementation
Subclass must provide
```

### 3. Concrete Operations
```javascript
Implemented in base class:

void step1() {
    // Common implementation
}

Shared by all subclasses
```javascript

### 4. Hook Methods
```javascript
Optional override points:

void hook() {
    // Default (often empty) implementation
}

Can be overridden if needed
Provides extension points
```javascript

## Benefits

**Code Reuse**: Common code in one place

**Control**: Base class controls algorithm flow

**Consistency**: Ensures algorithm structure is followed

**Easy Extension**: Add new implementations easily

**Inversion of Control**: Framework calls subclass methods

## Drawbacks

**Rigid Structure**: Algorithm flow is fixed

**Inheritance**: Tight coupling through inheritance

**Liskov Substitution**: Must maintain base class contract

**Limited Flexibility**: Can't change algorithm structure

## Template Method Flow
```javascript
┌────────────────────────────────────────────────────┐
│          Template Method Pattern Flow               │
└────────────────────────────────────────────────────┘

Step 1: Client calls template method
    object.templateMethod()
    ↓
Step 2: Template method executes algorithm
    step1() → common operation
    ↓
    step2() → abstract (subclass implements)
    ↓
    step3() → hook (subclass may override)
    ↓
    step4() → common operation
    ↓
Step 3: Algorithm completes
```javascript

## Hook Methods
```javascript
Optional customization points:

class Beverage {
    make() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {  // Hook
            addCondiments();
        }
    }
    
    // Hook with default implementation
    customerWantsCondiments() {
        return true;  // Default: yes
    }
}

class Tea extends Beverage {
    // Can override hook if needed
    customerWantsCondiments() {
        return false;  // Tea without condiments
    }
}
```

## Hollywood Principle

**"Don't call us, we'll call you"**
```javascript
Base class controls flow:
└─ Calls methods on subclass
└─ Subclass doesn't call base class methods
└─ Inversion of control

High-level component (base class)
└─ Calls low-level components (subclass methods)
```javascript

## Template Method vs Strategy
```javascript
┌────────────────────────────────────────────────────┐
│      Template Method vs Strategy Pattern            │
└────────────────────────────────────────────────────┘

Template Method              Strategy
├─ Uses inheritance          ├─ Uses composition
├─ Compile-time binding      ├─ Runtime binding
├─ Algorithm structure fixed ├─ Entire algorithm varies
├─ Subclass implements steps ├─ Strategy implements all
├─ Class-level reuse         ├─ Object-level flexibility
└─ Less flexible             └─ More flexible

Choose Template Method for fixed structure
Choose Strategy for interchangeable algorithms
```text

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│    Common Template Method Applications              │
└────────────────────────────────────────────────────┘

Frameworks
└─ Application lifecycle (init, run, cleanup)

Data Processing
└─ Read, process, write workflows

Testing Frameworks
└─ Setup, test, teardown

Build Tools
└─ Compile, test, package, deploy

Document Generation
└─ Header, body, footer formatting

Game Development
└─ Game loop (update, render)

Web Frameworks
└─ Request handling pipeline

Database Operations
└─ Connect, execute, disconnect
```javascript

## Best Practices

**Make Template Final**: Prevent override of algorithm structure

**Minimal Abstract Methods**: Only make varying steps abstract

**Use Hooks**: Provide optional extension points

**Document Steps**: Clearly explain each step's purpose

**Preserve Order**: Don't let subclasses change step order

**Consider Visibility**: Make steps protected, not public

**Clear Names**: Use descriptive method names

## Pros and Cons Summary
```javascript
✅ Pros
├─ Code reuse through inheritance
├─ Controls algorithm extension
├─ Eliminates code duplication
├─ Easy to add new implementations
├─ Enforces consistent structure
└─ Implements Hollywood Principle

❌ Cons
├─ Limited by inheritance
├─ Rigid algorithm structure
├─ Violates Liskov if not careful
├─ Less flexible than composition
└─ Tight coupling to base class
```

## Key Takeaways

- **Defines algorithm skeleton** in base class
- **Subclasses implement** specific steps
- **Algorithm structure** is fixed and controlled
- **Common code** centralized in base class
- **Uses inheritance** rather than composition
- **Use when**: Multiple classes share algorithm structure
- **Don't use when**: Need flexible algorithm changes

**Remember**: Template Method is about defining a fixed algorithm structure where certain steps vary. The base class controls the flow, and subclasses fill in the details. It's perfect when you have a well-defined process with varying implementations, but use composition-based patterns if you need more flexibility.

---
# Chain of Responsibility Pattern

The Chain of Responsibility pattern passes a request along a chain of handlers. Each handler decides either to process the request or to pass it to the next handler in the chain.

## What is Chain of Responsibility Pattern?

**Chain of Responsibility**: Passes requests along a chain until one handler processes it.

**Core Idea**: Multiple handlers, request flows through until handled

Think of **customer support escalation**:
- Level 1 support tries to help
- If can't solve, escalates to Level 2
- If still can't solve, escalates to Level 3
- Request passes through chain until resolved

## Problem It Solves

**Without Chain of Responsibility**:
```javascript
Hardcoded handler selection:

if (request.type === 'basic') {
    basicHandler.handle(request);
} else if (request.type === 'intermediate') {
    intermediateHandler.handle(request);
} else if (request.type === 'advanced') {
    advancedHandler.handle(request);
}

// Tight coupling
// Hard to add/remove handlers
// Client knows all handlers
```text

**With Chain of Responsibility**:
```javascript
Request flows through chain:

handler1.setNext(handler2);
handler2.setNext(handler3);
handler1.handle(request);

// Loose coupling
// Easy to add/remove handlers
// Client only knows first handler
```

## When to Use Chain of Responsibility

**Use When**:
- Multiple objects can handle a request
- Handler isn't known beforehand
- Want to issue request to one of several objects
- Set of handlers should be dynamic

**Don't Use When**:
- Every request must be handled (no guarantee)
- Order of handlers is critical and complex
- Simple if-else is clearer

## Structure
```text
┌──────────────┐
│   Client     │
└──────┬───────┘
       │ sends request to
       ▼
┌──────────────┐
│   Handler    │ (Interface)
├──────────────┤
│ - next       │
├──────────────┤
│ + setNext()  │
│ + handle()   │
└──────△───────┘
       │
   ┌───┴────────┬─────────┐
   │            │         │
┌──┴──────┐ ┌──┴──────┐ ┌┴────────┐
│HandlerA │ │HandlerB │ │HandlerC │
├─────────┤ ├─────────┤ ├─────────┤
│+handle()│ │+handle()│ │+handle()│
└─────────┘ └─────────┘ └─────────┘

Flow: A → B → C (until one handles it)
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│   Chain of Responsibility Pattern Components        │
└────────────────────────────────────────────────────┘

Handler Interface
└─ handle(request): Process or pass to next
└─ setNext(handler): Set next in chain

Concrete Handlers
└─ Implement handling logic
└─ Decide to process or pass along

Client
└─ Initiates request to first handler
└─ Doesn't know which handler will process
```text

## Real-World Examples

### 1. Authentication & Authorization
```
Chain:
├─ AuthenticationHandler
│   ├─ Check if user logged in
│   ├─ If yes, pass to next
│   └─ If no, reject request
├─ AuthorizationHandler
│   ├─ Check user permissions
│   ├─ If authorized, pass to next
│   └─ If not, reject request
└─ ValidationHandler
    ├─ Validate request data
    ├─ If valid, pass to next
    └─ If invalid, reject request

Request flows through all or stops at first failure
```text

### 2. Expense Approval
```
Chain based on amount:
├─ TeamLeadHandler (< $1,000)
│   └─ Can approve up to $1,000
├─ ManagerHandler (< $10,000)
│   └─ Can approve up to $10,000
└─ DirectorHandler (< $100,000)
    └─ Can approve up to $100,000

Expense $5,000:
└─ TeamLead can't approve, passes to Manager
└─ Manager approves
```text

### 3. Logging Levels
```
Chain by severity:
├─ ConsoleLogger (INFO and above)
│   └─ Logs to console, passes to next
├─ FileLogger (WARNING and above)
│   └─ Logs to file, passes to next
└─ EmailLogger (ERROR and above)
    └─ Sends email alert

INFO log:
└─ Console logs it, File and Email ignore

ERROR log:
└─ All three log it (Console, File, Email)
```text

### 4. Input Validation
```
Chain of validators:
├─ NotNullValidator
│   └─ Check if input is not null
├─ LengthValidator
│   └─ Check length constraints
├─ FormatValidator
│   └─ Check format (email, phone, etc.)
└─ BusinessRuleValidator
    └─ Check business logic

Each validator checks and passes along or rejects
```sql

### 5. Event Processing
```text
Chain of event handlers:
├─ CacheHandler
│   └─ Serve from cache if available
├─ DatabaseHandler
│   └─ Fetch from database if not cached
└─ APIHandler
    └─ Call external API if not in database

Request flows through until data is found
```

## Benefits

**Decoupling**: Sender doesn't know which handler processes request

**Flexibility**: Add/remove handlers dynamically

**Single Responsibility**: Each handler has one responsibility

**Order Control**: Control processing order by chain arrangement

**Dynamic Handling**: Handlers can be added at runtime

## Drawbacks

**No Guarantee**: Request might not be handled

**Debugging**: Hard to trace request through chain

**Performance**: Request travels through multiple handlers

**Configuration**: Setting up chain can be complex

## Chain of Responsibility Flow
```text
┌────────────────────────────────────────────────────┐
│      Chain of Responsibility Pattern Flow           │
└────────────────────────────────────────────────────┘

Step 1: Client sends request to first handler
    handler1.handle(request)
    ↓
Step 2: Handler1 checks if it can handle
    if (canHandle) → process and return
    else → pass to next
    ↓
Step 3: Handler2 checks if it can handle
    if (canHandle) → process and return
    else → pass to next
    ↓
Step 4: Handler3 checks if it can handle
    if (canHandle) → process and return
    else → no more handlers
    ↓
Step 5: Request either handled or reaches end of chain
```text

## Chain Variations

### 1. Stop After First Handler
```text
Each handler either:
└─ Processes request and stops
└─ Passes to next

Once handled, chain stops
```text

### 2. Process and Continue
```
Each handler:
└─ Processes request
└─ Always passes to next

All handlers in chain process request
Example: Logging at multiple levels
```text

### 3. Conditional Chain
```text
Handler decides:
└─ Process and stop
└─ Process and continue
└─ Skip and continue

Flexible processing
```

## Setting Up the Chain

### Static Chain
```javascript
Fixed at initialization:

handler1 = new Handler1();
handler2 = new Handler2();
handler3 = new Handler3();

handler1.setNext(handler2);
handler2.setNext(handler3);

Chain doesn't change at runtime
```text

### Dynamic Chain
```text
Built based on conditions:

chain = buildChain(userRole, requestType);

Can add/remove handlers at runtime
Flexible configuration
```

### Builder Pattern
```javascript
Use builder for complex chains:

chain = ChainBuilder
    .start(new AuthHandler())
    .then(new ValidateHandler())
    .then(new ProcessHandler())
    .build();

Clean, fluent API
```text

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│  Common Chain of Responsibility Applications        │
└────────────────────────────────────────────────────┘

Middleware
└─ Web frameworks (Express.js, ASP.NET)

Event Handling
└─ UI event bubbling, DOM events

Logging
└─ Different log levels and outputs

Approval Workflows
└─ Expense approval, document review

Request Processing
└─ HTTP request filters

Validation
└─ Multi-step validation

Error Handling
└─ Exception handling chain

Security
└─ Authentication and authorization layers
```text

## Chain of Responsibility vs Decorator
```text
┌────────────────────────────────────────────────────┐
│    Chain of Responsibility vs Decorator             │
└────────────────────────────────────────────────────┘

Chain of Responsibility      Decorator
├─ One handler processes     ├─ All decorators process
├─ Request may be rejected   ├─ Request always handled
├─ Sequential processing     ├─ Nested wrapping
├─ Handler decides to pass   ├─ Always delegates
├─ Can stop at any point     ├─ Goes through all layers
└─ Intent: Find handler      └─ Intent: Add behavior

Similar structure, different purpose
```

## Best Practices

**Define Termination**: Have a default handler at end

**Clear Responsibility**: Each handler has clear role

**Order Matters**: Arrange handlers logically

**Document Chain**: Explain handler order and purpose

**Avoid Cycles**: Ensure chain doesn't loop

**Handle Null**: Check if next handler exists

**Logging**: Log which handler processed request

## Example: HTTP Middleware
```text
Request → Middleware Chain → Response

├─ LoggingMiddleware
│   └─ Log request details
│   └─ Pass to next
├─ AuthenticationMiddleware
│   └─ Check authentication
│   └─ Reject or pass to next
├─ AuthorizationMiddleware
│   └─ Check permissions
│   └─ Reject or pass to next
├─ ValidationMiddleware
│   └─ Validate request data
│   └─ Reject or pass to next
└─ RouteHandler
    └─ Process request
    └─ Return response

Each middleware can stop chain or continue
```

## Pros and Cons Summary
```javascript
✅ Pros
├─ Decouples sender and receiver
├─ Flexible handler assignment
├─ Single Responsibility Principle
├─ Dynamic chain configuration
├─ Open/Closed Principle
└─ Easy to add new handlers

❌ Cons
├─ No guarantee of handling
├─ Hard to debug/trace
├─ Performance overhead
├─ Complex chain setup
└─ Request might be ignored
```sql

## Key Takeaways

- **Passes request along chain** of handlers
- **Each handler** decides to process or pass along
- **Decouples sender** from receiver
- **Dynamic and flexible** handler configuration
- **No guarantee** request will be handled
- **Use when**: Multiple objects might handle request
- **Don't use when**: Must guarantee request handling

**Remember**: Chain of Responsibility is about passing a request through a series of handlers until one processes it. It's perfect for scenarios like middleware, validation chains, and approval workflows where you don't know upfront which handler should process the request.

---
# Visitor Pattern

The Visitor pattern lets you add new operations to existing object structures without modifying the structures. It separates algorithms from the objects they operate on.

## What is Visitor Pattern?

**Visitor Pattern**: Adds new operations to objects without changing their classes.

**Core Idea**: Separate operations from object structure

Think of **home inspector**:
- House has rooms (structure)
- Inspector visits each room (visitor)
- Can have different inspectors: electrical, plumbing, safety
- Add new inspections without changing house structure

## Problem It Solves

**Without Visitor**:
```javascript
Adding new operations means modifying classes:

class Circle {
    draw() { }
    calculateArea() { }
    exportToXML() { }      // New operation - modify class
    exportToJSON() { }     // New operation - modify class
}

class Rectangle {
    draw() { }
    calculateArea() { }
    exportToXML() { }      // New operation - modify class
    exportToJSON() { }     // New operation - modify class
}

// Violates Open/Closed Principle
// Must modify every class for new operations
```javascript

**With Visitor**:
```javascript
Operations in separate visitor classes:

class XMLExportVisitor {
    visitCircle(circle) { }
    visitRectangle(rectangle) { }
}

class JSONExportVisitor {
    visitCircle(circle) { }
    visitRectangle(rectangle) { }
}

// Add new operations without modifying shape classes
```

## When to Use Visitor

**Use When**:
- Need to perform operations across object structure
- Object structure rarely changes but operations change often
- Want to keep related operations together
- Operations are unrelated to object's main responsibility

**Don't Use When**:
- Object structure changes frequently
- Few operations needed
- Operations are core to object's responsibility
- Adds too much complexity

## Structure
```text
┌──────────────┐
│   Visitor    │ (Interface)
├──────────────┤
│+visitA(elemA)│
│+visitB(elemB)│
└──────△───────┘
       │
       │ implements
       │
┌──────┴───────┐
│ConcreteVisitor│
├──────────────┤
│+visitA()     │
│+visitB()     │
└──────────────┘

┌──────────────┐
│   Element    │ (Interface)
├──────────────┤
│ + accept(v)  │
└──────△───────┘
       │
   ┌───┴────────┐
   │            │
┌──┴──────┐ ┌──┴──────┐
│ElementA │ │ElementB │
├─────────┤ ├─────────┤
│+accept()│ │+accept()│
└─────────┘ └─────────┘

accept(visitor) {
    visitor.visitA(this);
}
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│         Visitor Pattern Components                  │
└────────────────────────────────────────────────────┘

Visitor Interface
└─ Declares visit method for each element type

Concrete Visitor
└─ Implements operations for each element type

Element Interface
└─ Declares accept method taking visitor

Concrete Element
└─ Implements accept method
└─ Calls appropriate visitor method

Object Structure
└─ Can enumerate elements
└─ May provide high-level interface
```text

## Real-World Examples

### 1. Document Export
```javascript
Document elements:
├─ Paragraph
├─ Image
├─ Table
└─ Heading

Visitors (export formats):
├─ PDFExportVisitor
│   ├─ visitParagraph() → convert to PDF
│   ├─ visitImage() → embed image in PDF
│   └─ visitTable() → format table for PDF
├─ HTMLExportVisitor
│   ├─ visitParagraph() → <p> tags
│   ├─ visitImage() → <img> tag
│   └─ visitTable() → <table> tags
└─ MarkdownExportVisitor
    ├─ visitParagraph() → plain text
    ├─ visitImage() → ![alt](src)
    └─ visitTable() → markdown table

Add new export format without changing elements
```text

### 2. Shopping Cart Tax Calculator
```
Cart items:
├─ Book (tax-exempt)
├─ Electronics (10% tax)
├─ Food (5% tax)
└─ Clothing (8% tax)

Visitors:
├─ TaxCalculatorVisitor
│   ├─ visitBook() → 0% tax
│   ├─ visitElectronics() → 10% tax
│   ├─ visitFood() → 5% tax
│   └─ visitClothing() → 8% tax
└─ DiscountCalculatorVisitor
    ├─ visitBook() → 10% discount
    ├─ visitElectronics() → 5% discount
    └─ ... different discount per item type

Different calculations without modifying items
```text

### 3. File System Operations
```javascript
File system elements:
├─ File
├─ Directory
└─ Symlink

Visitors:
├─ SizeCalculatorVisitor
│   ├─ visitFile() → file size
│   ├─ visitDirectory() → sum of contents
│   └─ visitSymlink() → target size
├─ SearchVisitor
│   ├─ visitFile() → check if matches
│   ├─ visitDirectory() → search contents
│   └─ visitSymlink() → follow link
└─ PermissionCheckerVisitor
    └─ Check permissions for each type

New operations without changing file system structure
```text

### 4. Compiler AST Operations
```
AST nodes:
├─ NumberNode
├─ VariableNode
├─ BinaryOperationNode
└─ FunctionCallNode

Visitors:
├─ CodeGeneratorVisitor
│   └─ Generate code for each node type
├─ TypeCheckerVisitor
│   └─ Check types for each node
├─ OptimizerVisitor
│   └─ Optimize each node
└─ PrettyPrinterVisitor
    └─ Format code for each node

Multiple passes over AST with different visitors
```text

### 5. Insurance Policy Pricing
```
Policies:
├─ HealthInsurance
├─ CarInsurance
├─ HomeInsurance
└─ LifeInsurance

Visitors:
├─ PremiumCalculatorVisitor
│   └─ Calculate premium for each policy type
├─ RiskAssessorVisitor
│   └─ Assess risk for each policy type
└─ ClaimProcessorVisitor
    └─ Process claims for each policy type

Different calculations for same policy structure
```text

## Benefits

**Open/Closed Principle**: Add new operations without modifying classes

**Single Responsibility**: Related operations grouped in visitor

**Accumulate State**: Visitor can accumulate state while traversing

**Work Across Hierarchy**: Operate on unrelated classes

## Drawbacks

**Complexity**: Adds many classes and indirection

**Circular Dependency**: Elements know about visitors, visitors about elements

**Breaking Encapsulation**: Visitor may need access to element internals

**Hard to Add Elements**: Adding new element type requires updating all visitors

## Visitor Pattern Flow
```javascript
┌────────────────────────────────────────────────────┐
│            Visitor Pattern Flow                     │
└────────────────────────────────────────────────────┘

Step 1: Client creates visitor
    visitor = new ConcreteVisitor()
    ↓
Step 2: Client calls accept on element
    element.accept(visitor)
    ↓
Step 3: Element calls appropriate visit method
    visitor.visitElement(this)
    ↓
Step 4: Visitor performs operation
    // Operation specific to element type
    ↓
Step 5: Visitor returns result (if any)
    return result
```

## Double Dispatch
```javascript
Key mechanism of Visitor pattern:

First dispatch:
└─ element.accept(visitor)  // Based on element type

Second dispatch:
└─ visitor.visitElement(this)  // Based on visitor type

Result:
└─ Right visitor method for right element type
└─ Resolves at runtime
```javascript

## Common Variations

### 1. Accumulating Visitor
```javascript
Visitor accumulates results:

class TotalPriceVisitor {
    total = 0;
    
    visitItem(item) {
        this.total += item.price;
    }
    
    getTotal() {
        return this.total;
    }
}
```javascript

### 2. Filtering Visitor
```javascript
Visitor collects matching elements:

class FindVisitor {
    results = [];
    
    visitElement(element) {
        if (element.matches(criteria)) {
            this.results.push(element);
        }
    }
}
```

### 3. Transforming Visitor
```javascript
Visitor creates new structure:

class CloneVisitor {
    visitElement(element) {
        return new Element(element.data);
    }
}
```text

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│       Common Visitor Pattern Applications           │
└────────────────────────────────────────────────────┘

Compilers
└─ AST traversal, code generation, optimization

Reporting
└─ Generate different report formats

Tax/Pricing
└─ Calculate taxes, prices, discounts

File Operations
└─ Search, size calculation, backup

Document Processing
└─ Export to different formats

Graphics
└─ Rendering, hit testing, bounding box

Data Serialization
└─ XML, JSON, binary formats

Static Analysis
└─ Code metrics, lint rules
```sql

## Visitor vs Strategy
```text
┌────────────────────────────────────────────────────┐
│          Visitor vs Strategy Pattern                │
└────────────────────────────────────────────────────┘

Visitor                      Strategy
├─ Operations on structures  ├─ Interchangeable algorithms
├─ Multiple element types    ├─ Single context
├─ Double dispatch           ├─ Single dispatch
├─ Add operations easily     ├─ Change algorithm easily
├─ Hard to add elements      ├─ Easy to add strategies
└─ Intent: New operations    └─ Intent: Algorithm choice
```javascript

## Best Practices

**Stable Structure**: Use when object structure is stable

**Related Operations**: Group related operations in one visitor

**Access Control**: Provide necessary access to element internals

**Default Behavior**: Provide default visit methods

**Document Dependencies**: Clear which elements each visitor handles

**Null Safety**: Handle null elements gracefully

**Return Values**: Consider if visitors need return values

## Pros and Cons Summary
```javascript
✅ Pros
├─ Add new operations easily
├─ Related operations together
├─ Single Responsibility Principle
├─ Open/Closed Principle
├─ Accumulate state during traversal
└─ Work across class hierarchy

❌ Cons
├─ Hard to add new element types
├─ Breaks encapsulation
├─ Circular dependency
├─ Increased complexity
├─ Double dispatch overhead
└─ Must update all visitors for new elements
```

## When to Use Visitor Pattern

**Use When**:
- Stable object structure, changing operations
- Need to perform unrelated operations on structure
- Want to avoid polluting classes with many operations
- Operations need to work across object hierarchy

**Don't Use When**:
- Object structure changes frequently
- Operations are core to object's purpose
- Few operations needed
- Simpler approaches work

## Key Takeaways

- **Separates operations** from object structure
- **Add new operations** without modifying classes
- **Uses double dispatch** to resolve types
- **Groups related operations** in visitor classes
- **Hard to add new element types** (all visitors must change)
- **Use when**: Stable structure, varying operations
- **Don't use when**: Structure changes frequently

**Remember**: Visitor pattern is about adding operations to existing structures without modifying them. It's powerful when you have a stable object structure but need to frequently add new operations. Think of it as bringing operations to objects rather than embedding operations in objects. However, adding new element types is costly, so use it only when the structure is relatively stable.

---
# Mediator Pattern

The Mediator pattern defines an object that encapsulates how a set of objects interact. It promotes loose coupling by keeping objects from referring to each other explicitly.

## What is Mediator Pattern?

**Mediator Pattern**: Centralizes complex communications between objects in a mediator object.

**Core Idea**: Objects communicate through a mediator instead of directly

Think of **air traffic control**:
- Planes don't talk directly to each other
- All communicate through control tower
- Tower coordinates all planes
- Prevents chaotic direct communication

## Problem It Solves

**Without Mediator**:
```javascript
Direct communication - complex web of dependencies:

Button knows about TextField, Dialog, SaveButton
TextField knows about Button, Label, SaveButton
SaveButton knows about TextField, Dialog, Button
Label knows about TextField, Button

// Every object knows about every other object
// Tight coupling, hard to maintain
// Adding new component affects all others
```javascript

**With Mediator**:
```javascript
Communication through mediator:

Button → Mediator → TextField
TextField → Mediator → SaveButton
SaveButton → Mediator → Dialog

// Objects only know about mediator
// Loose coupling, easy to maintain
// Adding new component only affects mediator
```text

## When to Use Mediator

**Use When**:
- Objects communicate in complex but well-defined ways
- Reusing objects is difficult due to dependencies
- Behavior distributed among classes should be customizable
- Many objects communicate in structured way

**Don't Use When**:
- Communication is simple point-to-point
- Central mediator becomes too complex
- Adds unnecessary indirection

## Structure
```text
┌──────────────┐
│   Mediator   │ (Interface)
├──────────────┤
│ + notify()   │
└──────△───────┘
       │
       │ implements
       │
┌──────┴───────┐
│Concrete      │
│Mediator      │
├──────────────┤        ┌──────────────┐
│ - componentA │───────>│  Component   │
│ - componentB │        ├──────────────┤
│ - componentC │        │ - mediator   │
├──────────────┤        ├──────────────┤
│ + notify()   │        │ + operation()│
└──────────────┘        └──────△───────┘
                               │
                          ┌────┴─────┬─────────┐
                          │          │         │
                    ┌─────┴───┐ ┌────┴────┐ ┌─┴──────┐
                    │ComponentA│ │ComponentB│ │ComponentC│
                    └──────────┘ └─────────┘ └────────┘
```text

## Key Components
```text
┌────────────────────────────────────────────────────┐
│         Mediator Pattern Components                 │
└────────────────────────────────────────────────────┘

Mediator Interface
└─ Defines communication interface

Concrete Mediator
└─ Implements coordination logic
└─ Knows and maintains colleagues
└─ Coordinates their interactions

Colleague Classes
└─ Each knows its mediator
└─ Communicates through mediator only
└─ Independent of other colleagues
```

## Real-World Examples

### 1. Chat Room
```text
ChatMediator (Mediator):
└─ manages users
└─ sendMessage(message, from, to)
└─ broadcast(message, from)

Users (Colleagues):
├─ User1
├─ User2
└─ User3

User1.send("Hello") 
→ ChatMediator.broadcast()
→ Delivers to User2, User3

Users don't know about each other
All communication through mediator
```text

### 2. Form Dialog
```text
DialogMediator (Mediator):
└─ coordinates form components
└─ notify(component, event)

Components (Colleagues):
├─ TextField
│   └─ onChange → notify mediator
├─ CheckBox
│   └─ onToggle → notify mediator
├─ SubmitButton
│   └─ onClick → notify mediator
└─ ResetButton
    └─ onClick → notify mediator

When TextField changes:
└─ Notifies mediator
└─ Mediator enables/disables SubmitButton
└─ Mediator updates validation message

Components don't interact directly
```

### 3. Airport Tower
```text
ControlTower (Mediator):
└─ manages aircraft
└─ requestLanding(aircraft)
└─ requestTakeoff(aircraft)
└─ coordinates runway usage

Aircraft (Colleagues):
├─ CommercialPlane
├─ CargoPlane
└─ PrivateJet

Plane requests landing
→ Tower checks runway availability
→ Tower coordinates with other planes
→ Tower grants permission

Planes don't communicate directly
Tower prevents collisions
```text

### 4. Smart Home System
```text
HomeAutomationHub (Mediator):
└─ coordinates all devices
└─ deviceChanged(device, state)

Devices (Colleagues):
├─ Light
│   └─ motion detected → notify hub
├─ Thermostat
│   └─ temperature changed → notify hub
├─ SecurityCamera
│   └─ motion detected → notify hub
└─ DoorLock
    └─ unlocked → notify hub

Motion detected:
└─ Camera notifies hub
└─ Hub turns on lights
└─ Hub adjusts thermostat
└─ Hub records event

Devices don't know about each other
```

### 5. GUI Framework
```text
WindowMediator (Mediator):
└─ manages UI components
└─ componentEvent(component, event)

UI Components (Colleagues):
├─ Menu
├─ Toolbar
├─ StatusBar
└─ ContentArea

Menu item clicked:
└─ Menu notifies mediator
└─ Mediator updates toolbar
└─ Mediator updates status bar
└─ Mediator updates content

Components loosely coupled
```

## Benefits

**Loose Coupling**: Colleagues don't reference each other directly

**Centralized Control**: Interaction logic in one place

**Simplified Objects**: Colleagues are simpler, less dependencies

**Easier Maintenance**: Change interaction logic in one place

**Reusable Colleagues**: Components can be reused independently

## Drawbacks

**God Object**: Mediator can become too complex

**Single Point of Failure**: All communication goes through mediator

**Hard to Understand**: Interaction logic may be harder to follow

**Performance**: Extra layer of indirection

## Mediator Pattern Flow
```javascript
┌────────────────────────────────────────────────────┐
│            Mediator Pattern Flow                    │
└────────────────────────────────────────────────────┘

Step 1: Colleague state changes
    componentA.onChange()
    ↓
Step 2: Colleague notifies mediator
    mediator.notify(componentA, "change")
    ↓
Step 3: Mediator determines response
    // Check what needs to happen
    ↓
Step 4: Mediator updates other colleagues
    componentB.update()
    componentC.update()
    ↓
Step 5: System state synchronized
```text

## Communication Patterns

### 1. Event-Based
```text
Component triggers event:
└─ component.onEvent()
└─ mediator.notify(component, event)
└─ mediator updates others

Reactive, event-driven
```text

### 2. Direct Method Calls
```
Mediator calls components directly:
└─ mediator.updateComponent(data)
└─ component receives update

More controlled, less reactive
```text

### 3. Hybrid
```text
Combination:
└─ Components notify mediator (events)
└─ Mediator calls components (direct)

Flexible approach
```text

## Mediator vs Observer
```text
┌────────────────────────────────────────────────────┐
│         Mediator vs Observer Pattern                │
└────────────────────────────────────────────────────┘

Mediator                     Observer
├─ Centralized control       ├─ Distributed notification
├─ Complex interactions      ├─ Simple one-to-many
├─ Two-way communication     ├─ One-way notification
├─ Mediator knows colleagues ├─ Subject doesn't know observers
├─ Coordinates behavior      ├─ Broadcasts changes
└─ Intent: Decouple objects  └─ Intent: Notify dependents

Can be combined: Mediator uses Observer internally
```

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│       Common Mediator Pattern Applications          │
└────────────────────────────────────────────────────┘

GUI Systems
└─ Dialog boxes, form validation

Chat Applications
└─ Chat rooms, group messaging

Air Traffic Control
└─ Coordinating aircraft

Smart Home
└─ Device coordination, automation

Workflow Systems
└─ Process coordination

Game Development
└─ Game object coordination

Microservices
└─ Service orchestration

Event Systems
└─ Event bus, message broker
```text

## Implementation Variations

### 1. Simple Mediator
```text
Mediator just forwards messages:

notify(sender, event) {
    if (sender === componentA) {
        componentB.update(event);
    }
}

Straightforward routing
```javascript

### 2. Smart Mediator
```javascript
Mediator contains business logic:

notify(sender, event) {
    // Complex coordination logic
    // State management
    // Validation
    // Multiple component updates
}

More intelligent coordination
```javascript

### 3. Event Bus
```javascript
Generic event routing:

publish(event, data) {
    subscribers.forEach(sub => {
        if (sub.interestedIn(event)) {
            sub.handle(data);
        }
    });
}

Flexible, decoupled
```

## Best Practices

**Keep Mediator Focused**: Don't let it become god object

**Clear Responsibilities**: Define what mediator coordinates

**Document Interactions**: Explain coordination logic

**Consider Observers**: Use Observer pattern within mediator

**Avoid Business Logic**: Keep domain logic in colleagues

**Testability**: Make mediator easy to test

**Logging**: Log coordination for debugging

## Pros and Cons Summary
```text
✅ Pros
├─ Reduces coupling between components
├─ Centralizes interaction logic
├─ Simplifies object protocols
├─ Components more reusable
├─ Easier to understand interactions
└─ Single Responsibility Principle

❌ Cons
├─ Mediator can become complex
├─ Single point of failure
├─ May become god object
├─ Extra layer of indirection
├─ Can be harder to trace flow
└─ Performance overhead
```

## Key Takeaways

- **Centralizes complex communications** in mediator
- **Reduces coupling** between interacting objects
- **Objects communicate** only through mediator
- **Simplifies individual objects** by removing dependencies
- **Risk of complex mediator** (god object)
- **Use when**: Many objects interact in complex ways
- **Don't use when**: Simple point-to-point communication

**Remember**: Mediator pattern is about reducing chaotic dependencies between objects by introducing a central coordinator. It's like a traffic controller that manages interactions. Use it when objects have complex interaction patterns, but be careful not to let the mediator become too complex itself. Sometimes combining Mediator with Observer pattern provides the best solution.

---
# Memento Pattern

The Memento pattern captures and externalizes an object's internal state without violating encapsulation, so it can be restored later.

## What is Memento Pattern?

**Memento Pattern**: Saves and restores an object's previous state.

**Core Idea**: Snapshot an object's state for later restoration

Think of **save points in games**:
- Game saves current state
- Player can load saved state anytime
- Game state restored exactly as it was
- Multiple save points possible

## Problem It Solves

**Without Memento**:
```javascript
No way to save/restore state:

class TextEditor {
    text = "";
    
    type(newText) {
        this.text += newText;
    }
    
    // Can't undo - no saved state!
}

editor.type("Hello");
editor.type(" World");
// Want to go back to "Hello"?
// No way to restore!
```

**With Memento**:
```text
Save and restore state:

editor.type("Hello");
saved = editor.save();     // Save state
editor.type(" World");
editor.restore(saved);     // Back to "Hello"

// Clean state management
// Doesn't expose internals
```

## When to Use Memento

**Use When**:
- Need undo/redo functionality
- Need to save and restore object state
- Want snapshots of object state
- Must preserve encapsulation while saving state

**Don't Use When**:
- State is simple (just copy values)
- Many snapshots needed (memory concern)
- Doesn't need state restoration

## Structure
```text
┌──────────────┐
│  Originator  │
├──────────────┤
│ - state      │
├──────────────┤
│ + save()     │──creates──> ┌──────────┐
│ + restore()  │<--uses---   │ Memento  │
└──────────────┘             ├──────────┤
                             │ - state  │
                             ├──────────┤
                             │+ getState│
                             └──────────┘
                                  │
                             stored by
                                  │
                                  ▼
                          ┌──────────────┐
                          │  Caretaker   │
                          ├──────────────┤
                          │ - history[]  │
                          ├──────────────┤
                          │ + save()     │
                          │ + undo()     │
                          └──────────────┘
```

## Key Components
```sql
┌────────────────────────────────────────────────────┐
│         Memento Pattern Components                  │
└────────────────────────────────────────────────────┘

Originator
└─ Creates mementos of its own state
└─ Restores state from memento
└─ Only class that can access memento's state

Memento
└─ Stores originator's internal state
└─ Protects against access by other objects
└─ Snapshot of state at specific point

Caretaker
└─ Keeps track of mementos (history)
└─ Decides when to save/restore
└─ Never modifies memento content
```

## Real-World Examples

### 1. Text Editor
```text
TextEditor (Originator):
└─ text content
└─ cursor position
└─ save() → creates Memento
└─ restore(memento) → restores state

TextMemento (Memento):
└─ stored text
└─ stored cursor position

History (Caretaker):
└─ mementos[] (undo stack)
└─ save() → push current state
└─ undo() → pop and restore

editor.type("Hello");
editor.save();              // Save state
editor.type(" World");
editor.undo();              // Back to "Hello"
```

### 2. Online Shopping Cart
```text
ShoppingCart (Originator):
└─ items[]
└─ total amount
└─ save() → snapshot cart
└─ restore(memento) → restore cart

CartMemento (Memento):
└─ saved items[]
└─ saved total

CartHistory (Caretaker):
└─ snapshots[]
└─ save() → save current cart
└─ restore() → go back to saved cart

cart.addItem(item1);
cart.save();
cart.addItem(item2);
cart.restore();  // Back to just item1
```

### 3. Document Drafts
```text
Document (Originator):
└─ content
└─ metadata
└─ save() → create draft
└─ restore(draft) → restore version

DocumentMemento (Memento):
└─ saved content
└─ saved metadata
└─ timestamp

DraftManager (Caretaker):
└─ drafts[] (version history)
└─ saveDraft()
└─ restoreDraft(version)

Multiple drafts stored over time
Can restore any previous version
```

### 4. Game State
```text
Game (Originator):
└─ playerPosition
└─ playerHealth
└─ inventory[]
└─ score
└─ save() → create save point
└─ load(savePoint) → restore state

SavePoint (Memento):
└─ all game state data
└─ timestamp

SaveManager (Caretaker):
└─ savePoints[]
└─ createSavePoint()
└─ loadSavePoint(id)

Multiple save points in different locations
```

### 5. Database Transaction
```text
Connection (Originator):
└─ transaction state
└─ pending changes
└─ save() → create checkpoint
└─ restore() → rollback to checkpoint

TransactionMemento (Memento):
└─ saved state at checkpoint

TransactionManager (Caretaker):
└─ checkpoints[]
└─ createCheckpoint()
└─ rollback()

Supports nested transactions with checkpoints
```

## Benefits

**Encapsulation**: State saved/restored without exposing internals

**Undo/Redo**: Easy implementation of undo functionality

**Snapshots**: Multiple snapshots can coexist

**Decoupling**: Caretaker doesn't know about internal state

**Flexibility**: Can save state at any point

## Drawbacks

**Memory**: Each memento stores complete state

**Copying Cost**: Deep copying state can be expensive

**Complexity**: Additional classes to manage

**Storage**: History can grow very large

## Memento Pattern Flow
```javascript
┌────────────────────────────────────────────────────┐
│              Memento Pattern Flow                   │
└────────────────────────────────────────────────────┘

Save:
Step 1: Caretaker requests save
    caretaker.save()
    ↓
Step 2: Caretaker calls originator.save()
    memento = originator.save()
    ↓
Step 3: Originator creates memento
    return new Memento(this.state)
    ↓
Step 4: Caretaker stores memento
    history.push(memento)

Restore:
Step 1: Caretaker requests undo
    caretaker.undo()
    ↓
Step 2: Caretaker gets last memento
    memento = history.pop()
    ↓
Step 3: Caretaker calls restore
    originator.restore(memento)
    ↓
Step 4: Originator restores state
    this.state = memento.getState()
```

## Memento Variations

### 1. Simple Memento
```javascript
Stores single snapshot:

class Memento {
    constructor(state) {
        this.state = deepCopy(state);
    }
}

Basic save and restore
```

### 2. Incremental Memento
```javascript
Stores only changes (delta):

class DeltaMemento {
    constructor(changes) {
        this.changes = changes;  // Only what changed
    }
}

More memory efficient
Harder to implement
```

### 3. Timestamped Memento
```javascript
Adds timestamp to snapshot:

class Memento {
    constructor(state) {
        this.state = state;
        this.timestamp = Date.now();
    }
}

Useful for version history
Can restore to specific time
```

## History Management

### Stack-Based (Undo Only)
```text
history = [m1, m2, m3, m4]  ← top

undo() → pop m4, restore
history = [m1, m2, m3]

Simple undo, no redo
```

### Double Stack (Undo and Redo)
```sql
undoStack = [m1, m2, m3]
redoStack = []

undo():
└─ pop m3 from undo → push to redo
└─ restore m2

redo():
└─ pop m3 from redo → push to undo
└─ restore m3

Supports both undo and redo
```

### Limited History
```text
Max history size:

save(memento) {
    if (history.length >= maxSize) {
        history.shift();  // Remove oldest
    }
    history.push(memento);
}

Prevents memory overflow
```

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│       Common Memento Pattern Applications           │
└────────────────────────────────────────────────────┘

Text Editors
└─ Undo/redo typed text

IDEs
└─ Code changes, refactoring undo

Games
└─ Save points, checkpoint system

Databases
└─ Transaction rollback

Graphic Editors
└─ Undo drawing operations

Form Applications
└─ Save and restore form states

Configuration
└─ Save and restore settings

Workflow Systems
└─ Process state snapshots
```

## Memento vs Command Pattern
```text
┌────────────────────────────────────────────────────┐
│          Memento vs Command Pattern                 │
└────────────────────────────────────────────────────┘

Memento                      Command
├─ Saves complete state      ├─ Saves individual actions
├─ Restores full state       ├─ Reverses specific action
├─ Simple implementation     ├─ More complex undo logic
├─ More memory usage         ├─ Less memory (actions only)
├─ No action tracking        ├─ Tracks all actions
└─ Intent: State snapshot    └─ Intent: Reversible actions

Can be combined: Command uses Memento for undo
```

## Best Practices

**Deep Copy**: Ensure memento has independent copy of state

**Limit History**: Set maximum number of saved states

**Immutable Mementos**: Don't allow modification after creation

**Memory Management**: Clean up old mementos when not needed

**Clear Naming**: Use descriptive names for saved states

**Encapsulation**: Only originator accesses memento internals

**Timestamps**: Add timestamps for version tracking

## Pros and Cons Summary
```text
✅ Pros
├─ Preserves encapsulation
├─ Simple undo/redo implementation
├─ Multiple snapshots possible
├─ Decoupled state management
├─ Flexible restoration
└─ Clean separation of concerns

❌ Cons
├─ Memory consumption
├─ Deep copying overhead
├─ Additional classes
├─ History management complexity
├─ State synchronization issues
└─ Can be expensive for large states
```

## Key Takeaways

- **Captures object state** as snapshot
- **Restores state** without exposing internals
- **Preserves encapsulation** of originator
- **Three roles**: Originator, Memento, Caretaker
- **Memory trade-off** for undo capability
- **Use when**: Need undo/redo or state snapshots
- **Don't use when**: Memory is critical or state is simple

**Remember**: Memento pattern is about taking snapshots of object state for later restoration. It's the pattern behind undo/redo functionality. The key challenge is balancing memory usage with the number of snapshots you need to maintain. Use it when you need to save and restore state while keeping the object's internals private.

---
# Null Object Pattern

The Null Object pattern provides a default object with do-nothing behavior to avoid null checks throughout the code.

## What is Null Object Pattern?

**Null Object Pattern**: Replaces null references with a special object that has default do-nothing behavior.

**Core Idea**: Instead of checking for null, use a harmless default object

Think of a **substitute teacher**:
- Real teacher is absent (null)
- Substitute teacher steps in (null object)
- Class continues normally
- No disruption from teacher's absence

## Problem It Solves

**Without Null Object**:
```javascript
Null checks everywhere:

function processUser(user) {
    if (user !== null) {
        if (user.name !== null) {
            console.log(user.name);
        }
        if (user.getAddress() !== null) {
            console.log(user.getAddress());
        }
        if (user.getDiscount() !== null) {
            price = price - user.getDiscount();
        }
    }
}

// Verbose code
// Easy to forget null checks
// Null pointer exceptions risk
```

**With Null Object**:
```javascript
No null checks needed:

function processUser(user) {
    console.log(user.name);         // Works for both
    console.log(user.getAddress()); // Returns default
    price = price - user.getDiscount(); // Returns 0
}

// Clean, readable code
// No null checks required
// Safe by default
```

## When to Use Null Object

**Use When**:
- Null checks are repeated throughout code
- Default behavior makes sense for null case
- Want to simplify conditional logic
- Interface has clear do-nothing defaults

**Don't Use When**:
- Null represents meaningful error condition
- Need to detect absence of object
- Default behavior is unclear
- Hides bugs by silently doing nothing

## Structure
```text
┌──────────────┐
│  Interface   │
├──────────────┤
│ + operation()│
└──────△───────┘
       │
   ┌───┴────────┐
   │            │
┌──┴──────┐ ┌──┴──────────┐
│  Real   │ │  Null       │
│  Object │ │  Object     │
├─────────┤ ├─────────────┤
│+operation│ │+operation() │
│(real)   │ │ (do nothing)│
└─────────┘ └─────────────┘
```

## Key Components
```text
┌────────────────────────────────────────────────────┐
│       Null Object Pattern Components                │
└────────────────────────────────────────────────────┘

Interface
└─ Common interface for real and null objects

Real Object
└─ Normal implementation with actual behavior

Null Object
└─ Implements same interface
└─ Do-nothing or default behavior
└─ Safe operations that never fail

Client
└─ Uses interface
└─ Doesn't need to check for null
```

## Real-World Examples

### 1. Logger
```bash
Logger Interface:
└─ log(message)

RealLogger:
└─ log(message) → writes to file/console

NullLogger:
└─ log(message) → does nothing

Usage:
class Service {
    constructor(logger) {
        this.logger = logger || new NullLogger();
    }
    
    process() {
        this.logger.log("Processing...");
        // Works whether logger is real or null
    }
}

// With logging
service = new Service(new RealLogger());

// Without logging (no null checks)
service = new Service(new NullLogger());
```

### 2. Discount Strategy
```bash
Discount Interface:
└─ calculate(price)
└─ getDescription()

RealDiscount:
└─ calculate(price) → price * percentage
└─ getDescription() → "10% off"

NullDiscount:
└─ calculate(price) → 0 (no discount)
└─ getDescription() → "No discount"

Usage:
class Order {
    constructor(discount) {
        this.discount = discount || new NullDiscount();
    }
    
    getTotal(price) {
        return price - this.discount.calculate(price);
        // Works with or without discount
    }
}
```

### 3. User Profile
```javascript
User Interface:
└─ getName()
└─ getEmail()
└─ getAvatar()

RealUser:
└─ getName() → "Alice"
└─ getEmail() → "alice@example.com"
└─ getAvatar() → "/avatars/alice.png"

NullUser (Guest):
└─ getName() → "Guest"
└─ getEmail() → "N/A"
└─ getAvatar() → "/avatars/default.png"

Usage:
function displayProfile(user) {
    console.log(user.getName());
    console.log(user.getEmail());
    // Works for both logged-in and guest users
}

// Logged in user
displayProfile(new RealUser("Alice"));

// Not logged in
displayProfile(new NullUser());
```

### 4. Payment Method
```text
PaymentMethod Interface:
└─ pay(amount)
└─ getLabel()

RealPayment:
└─ pay(amount) → process payment
└─ getLabel() → "Credit Card"

NullPayment:
└─ pay(amount) → returns false (no payment)
└─ getLabel() → "No Payment Method"

Useful for draft orders that aren't paid yet
```

### 5. Notification Service
```bash
Notifier Interface:
└─ send(message)

EmailNotifier:
└─ send(message) → sends email

NullNotifier:
└─ send(message) → does nothing

Usage:
class OrderService {
    constructor(notifier) {
        this.notifier = notifier || new NullNotifier();
    }
    
    placeOrder(order) {
        // Process order
        this.notifier.send("Order placed!");
        // Works without notification setup
    }
}
```

## Benefits

**Eliminates Null Checks**: No if-null conditions needed

**Cleaner Code**: Simpler, more readable code

**Default Behavior**: Sensible defaults without special handling

**Consistent Interface**: Same interface for real and null objects

**Prevents Errors**: No null pointer exceptions

**Easier Testing**: Can use null objects in tests

## Drawbacks

**Hides Bugs**: Null behavior may mask real issues

**Hard to Debug**: Silent do-nothing can be confusing

**Overuse Risk**: May hide cases where null means error

**Not Always Appropriate**: Some cases null is meaningful signal

## Null Object vs Null Check
```text
┌────────────────────────────────────────────────────┐
│         Null Object vs Null Check                   │
└────────────────────────────────────────────────────┘

Null Check                   Null Object
├─ if (obj !== null)         ├─ No checks needed
├─ Scattered throughout code ├─ Clean code
├─ Easy to forget            ├─ Safe by default
├─ Explicit                  ├─ Implicit behavior
├─ Clear error detection     ├─ May hide errors
└─ Simple approach           └─ Requires extra class
```

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│      Common Null Object Applications                │
└────────────────────────────────────────────────────┘

Logging
└─ NullLogger when logging disabled

Caching
└─ NullCache when caching disabled

Authentication
└─ Guest user when not logged in

Discounts
└─ No discount by default

Notifications
└─ NullNotifier when notifications off

Configuration
└─ Default config when none provided

Rendering
└─ NullRenderer in headless mode

Database
└─ NullRepository for testing
```

## Implementation Tips

### Factory Method
```bash
Use factory to provide correct object:

class UserFactory {
    static getUser(id) {
        const user = database.find(id);
        return user || new NullUser();
    }
}

// Client always gets valid object
const user = UserFactory.getUser(123);
user.getName();  // Always safe
```

### Default Parameters
```javascript
Use as default parameter:

class Service {
    constructor(logger = new NullLogger()) {
        this.logger = logger;
    }
}

// NullLogger used when no logger provided
const service = new Service();
```

### Repository Pattern
```javascript
NullRepository for testing:

class NullUserRepository {
    findById(id) { return new NullUser(); }
    save(user) { return true; }
    delete(id) { return true; }
}

// Test without database
const repo = new NullUserRepository();
```

## Pros and Cons Summary
```javascript
✅ Pros
├─ Eliminates null checks
├─ Cleaner, readable code
├─ Prevents null exceptions
├─ Consistent interface usage
├─ Easy to test
└─ Default behavior handling

❌ Cons
├─ Can hide real bugs
├─ Silent failure behavior
├─ Extra class to maintain
├─ Not always appropriate
├─ Can mask error conditions
└─ May confuse developers
```

## Key Takeaways

- **Replaces null** with default do-nothing object
- **Eliminates null checks** throughout code
- **Same interface** for real and null objects
- **Prevents null pointer exceptions**
- **Be careful** not to hide real errors
- **Use when**: Repeated null checks, clear default behavior
- **Don't use when**: Null represents meaningful error

**Remember**: Null Object pattern is about providing safe defaults instead of null references. It makes code cleaner by eliminating null checks, but use it wisely - sometimes null is the correct signal that something is missing, and silently doing nothing might hide bugs.

---
# Repository Pattern

The Repository pattern abstracts the data layer by providing a collection-like interface for accessing domain objects, separating business logic from data access logic.

## What is Repository Pattern?

**Repository Pattern**: Acts as intermediary between domain objects and data storage.

**Core Idea**: Treat data access like a collection of objects

Think of a **library**:
- Librarian (Repository) manages books
- You ask librarian for books (don't access shelves directly)
- Librarian knows where books are stored
- You don't care about storage details

## Problem It Solves

**Without Repository**:
```sql
Business logic mixed with data access:

class UserService {
    getUser(id) {
        // Direct database access in business logic
        const connection = connectToDatabase();
        const query = `SELECT * FROM users WHERE id = ${id}`;
        const result = connection.execute(query);
        connection.close();
        return new User(result);
    }
}

// Business logic knows database details
// Hard to test
// Hard to switch databases
// Tight coupling
```

**With Repository**:
```javascript
Clean separation:

class UserService {
    constructor(userRepository) {
        this.userRepo = userRepository;
    }
    
    getUser(id) {
        return this.userRepo.findById(id);
        // Clean, simple business logic
    }
}

// Database details hidden in repository
// Easy to test with mock repository
// Easy to switch databases
```

## When to Use Repository

**Use When**:
- Want to separate business logic from data access
- Need to switch data sources easily
- Want to simplify testing
- Have complex data access logic
- Multiple services access same data

**Don't Use When**:
- Simple CRUD with no business logic
- Single data source that won't change
- Adds unnecessary abstraction layer

## Structure
```text
┌──────────────┐
│   Service    │ (Business Logic)
└──────┬───────┘
       │ uses
       ▼
┌──────────────┐
│ Repository   │ (Interface)
├──────────────┤
│ + findById() │
│ + findAll()  │
│ + save()     │
│ + delete()   │
└──────△───────┘
       │
       │ implements
       │
┌──────┴───────┐
│  Concrete    │
│  Repository  │
├──────────────┤
│ - dataSource │
├──────────────┤
│ + findById() │
│ + findAll()  │
│ + save()     │
│ + delete()   │
└──────┬───────┘
       │ accesses
       ▼
┌──────────────┐
│   Database   │
└──────────────┘
```

## Key Components
```text
┌────────────────────────────────────────────────────┐
│        Repository Pattern Components                │
└────────────────────────────────────────────────────┘

Repository Interface
└─ Defines standard CRUD operations
└─ Collection-like interface

Concrete Repository
└─ Implements data access logic
└─ Handles database queries
└─ Maps data to domain objects

Domain Model
└─ Business objects
└─ Independent of data source

Service Layer
└─ Uses repository for data access
└─ Contains business logic
```

## Standard Repository Methods
```text
┌────────────────────────────────────────────────────┐
│         Common Repository Methods                   │
└────────────────────────────────────────────────────┘

findById(id)
└─ Returns single entity by ID
└─ Returns null if not found

findAll()
└─ Returns all entities
└─ Can accept filter/pagination params

save(entity)
└─ Creates or updates entity
└─ Returns saved entity

delete(id)
└─ Removes entity by ID
└─ Returns boolean success

exists(id)
└─ Checks if entity exists
└─ Returns boolean

count()
└─ Returns total number of entities
```

## Real-World Examples

### 1. User Repository
```sql
UserRepository Interface:
├─ findById(id)
├─ findByEmail(email)
├─ findAll()
├─ save(user)
└─ delete(id)

MySQLUserRepository:
├─ findById(id) → SELECT * FROM users WHERE id = ?
├─ findByEmail(email) → SELECT * FROM users WHERE email = ?
├─ findAll() → SELECT * FROM users
├─ save(user) → INSERT/UPDATE users
└─ delete(id) → DELETE FROM users WHERE id = ?

PostgresUserRepository:
└─ Same interface, PostgreSQL queries

MongoUserRepository:
└─ Same interface, MongoDB operations

Service uses interface, doesn't know which DB
```

### 2. Product Repository
```javascript
ProductRepository Interface:
├─ findById(id)
├─ findByCategory(category)
├─ findByPriceRange(min, max)
├─ save(product)
└─ delete(id)

ProductService:
└─ constructor(productRepository)
└─ getProductsByCategory(category)
    └─ return this.repo.findByCategory(category)

Repository handles all database details
Service only thinks about business logic
```

### 3. Order Repository
```text
OrderRepository Interface:
├─ findById(id)
├─ findByCustomer(customerId)
├─ findByStatus(status)
├─ findByDateRange(start, end)
├─ save(order)
└─ delete(id)

OrderService:
└─ uses OrderRepository
└─ getRecentOrders(customerId)
└─ processOrder(order)

Complex queries hidden in repository
```

## Benefits

**Separation of Concerns**: Business logic separate from data access

**Testability**: Easy to mock repositories for testing

**Flexibility**: Switch data sources without changing business logic

**DRY**: Centralize data access logic

**Maintainability**: Data access changes don't affect services

**Consistency**: Uniform data access across application

## Drawbacks

**Extra Layer**: Additional abstraction

**Over-Engineering**: Overkill for simple applications

**Complexity**: More classes to maintain

**Leaky Abstractions**: Complex queries may expose data layer details

## Repository Pattern Flow
```sql
┌────────────────────────────────────────────────────┐
│            Repository Pattern Flow                  │
└────────────────────────────────────────────────────┘

Step 1: Service needs data
    service.getUser(id)
    ↓
Step 2: Service calls repository
    userRepository.findById(id)
    ↓
Step 3: Repository queries database
    SELECT * FROM users WHERE id = ?
    ↓
Step 4: Repository maps result to domain object
    return new User(result)
    ↓
Step 5: Service receives domain object
    // Uses User object for business logic
```

## Repository vs DAO (Data Access Object)
```text
┌────────────────────────────────────────────────────┐
│           Repository vs DAO                         │
└────────────────────────────────────────────────────┘

Repository                   DAO
├─ Domain-driven             ├─ Database-driven
├─ Returns domain objects    ├─ Returns data transfer objects
├─ Collection-like interface ├─ SQL-like interface
├─ Business oriented         ├─ Data oriented
├─ Can have business logic   ├─ Only data access
└─ Higher abstraction        └─ Closer to database

Repository is higher-level abstraction over DAO
```

## Testing with Repositories

### Mock Repository
```javascript
class MockUserRepository {
    constructor() {
        this.users = [];
    }
    
    findById(id) {
        return this.users.find(u => u.id === id);
    }
    
    save(user) {
        this.users.push(user);
        return user;
    }
    
    delete(id) {
        this.users = this.users.filter(u => u.id !== id);
        return true;
    }
}

// Test service without database
const repo = new MockUserRepository();
const service = new UserService(repo);
```

### In-Memory Repository
```bash
class InMemoryRepository {
    constructor() {
        this.store = new Map();
    }
    
    findById(id) {
        return this.store.get(id) || null;
    }
    
    save(entity) {
        this.store.set(entity.id, entity);
        return entity;
    }
    
    findAll() {
        return Array.from(this.store.values());
    }
    
    delete(id) {
        return this.store.delete(id);
    }
}

// Fast, no external dependencies
// Perfect for unit testing
```

## Generic Repository
```javascript
Base repository for all entities:

class GenericRepository {
    findById(id) { }
    findAll() { }
    save(entity) { }
    delete(id) { }
}

// Specific repositories extend it
class UserRepository extends GenericRepository {
    findByEmail(email) { }  // Additional methods
}

class ProductRepository extends GenericRepository {
    findByCategory(category) { }
}

Common logic in base, specific in subclass
```

## Common Use Cases
```text
┌────────────────────────────────────────────────────┐
│      Common Repository Pattern Applications         │
└────────────────────────────────────────────────────┘

User Management
└─ CRUD operations on users

Product Catalog
└─ Product search and storage

Order Processing
└─ Order queries and persistence

Content Management
└─ Articles, posts, pages

E-commerce
└─ Products, orders, customers

Authentication
└─ User credentials storage

Notification
└─ Notification history storage

Settings
└─ Configuration persistence
```

## Best Practices

**Interface First**: Define repository interface before implementation

**Domain Objects**: Return domain objects, not raw data

**Single Responsibility**: Each repository handles one entity

**Custom Methods**: Add query methods specific to domain needs

**Dependency Injection**: Inject repositories into services

**Generic Base**: Use base repository for common operations

**Error Handling**: Handle not-found and duplicate cases

**Naming Convention**: Name methods clearly (findByEmail, not query1)

## Pros and Cons Summary
```text
✅ Pros
├─ Clean separation of concerns
├─ Easy to test with mocks
├─ Switch data sources easily
├─ Centralized data access
├─ Consistent data operations
├─ DRY principle
└─ Maintainable codebase

❌ Cons
├─ Additional abstraction layer
├─ Overkill for simple apps
├─ More classes to maintain
├─ Complex queries can leak details
├─ Requires good interface design
└─ Extra development time
```

## Key Takeaways

- **Separates business logic** from data access
- **Collection-like interface** for data operations
- **Easy to test** with mock repositories
- **Flexible data sources** without changing business logic
- **Standard CRUD methods** plus domain-specific queries
- **Use when**: Want clean separation and testability
- **Don't use when**: Simple app with basic data access

**Remember**: Repository pattern is about creating a clean boundary between your business logic and how data is stored. Think of it as a collection that your services interact with. The actual storage mechanism (MySQL, MongoDB, in-memory) is hidden behind the repository interface, making your code flexible and testable.

---
# MVC Pattern

The MVC (Model-View-Controller) pattern separates an application into three interconnected components: Model, View, and Controller, each with specific responsibilities.

## What is MVC Pattern?

**MVC Pattern**: Separates application into Model, View, and Controller.

**Core Idea**: Separate data, presentation, and control logic

Think of a **restaurant**:
- Menu (Model) - what food is available
- Dining Room (View) - how food is presented
- Waiter (Controller) - takes orders and coordinates

## The Three Components
```sql
┌────────────────────────────────────────────────────┐
│              MVC Components                         │
└────────────────────────────────────────────────────┘

Model
└─ Data and business logic
└─ Database interactions
└─ Data validation
└─ Independent of UI

View
└─ User interface
└─ Displays data from Model
└─ Sends user input to Controller
└─ No business logic

Controller
└─ Handles user input
└─ Updates Model
└─ Selects View to render
└─ Coordinates Model and View
```

## Problem It Solves

**Without MVC**:
```javascript
Everything mixed together:

class Application {
    // Data logic
    users = [];
    
    // Business logic
    validateUser(user) { }
    
    // UI rendering
    renderUserList() {
        return '<div>' + this.users.map(...) + '</div>';
    }
    
    // Input handling
    handleClick(event) { }
}

// Hard to maintain
// Can't reuse components
// Difficult to test
```

**With MVC**:
```text
Clean separation:

UserModel → handles user data
UserView → renders user interface
UserController → coordinates both

// Each component has single responsibility
// Easy to maintain and test
// Components reusable
```

## Structure
```text
         User Action
              │
              ▼
┌──────────────────────┐
│      Controller      │
│  - Handles input     │
│  - Updates model     │
│  - Selects view      │
└───┬──────────────┬───┘
    │              │
    │ updates      │ selects
    ▼              ▼
┌─────────┐  ┌─────────┐
│  Model  │  │  View   │
│  Data   │  │   UI    │
│  Logic  │  │  Layer  │
└────┬────┘  └────△────┘
     │            │
     └────────────┘
     notifies (Model changes
     trigger View updates)
```

## Real-World Examples

### 1. User Management System
```sql
UserModel:
├─ users data
├─ addUser(user)
├─ removeUser(id)
├─ findUser(id)
└─ validateUser(user)

UserView:
├─ renderUserList()
├─ renderUserForm()
├─ renderUserDetails(user)
└─ showError(message)

UserController:
├─ handleAddUser(data)
│   └─ validates → saves to model → updates view
├─ handleDeleteUser(id)
│   └─ removes from model → updates view
└─ handleViewUser(id)
    └─ gets from model → renders in view
```

### 2. Shopping Cart
```text
CartModel:
├─ items[]
├─ addItem(item)
├─ removeItem(id)
├─ calculateTotal()
└─ updateQuantity(id, qty)

CartView:
├─ renderCart()
├─ renderItem(item)
├─ renderTotal(amount)
└─ showEmptyCart()

CartController:
├─ handleAddToCart(item)
├─ handleRemoveItem(id)
└─ handleCheckout()
```

### 3. Blog Application
```text
PostModel:
├─ posts[]
├─ createPost(data)
├─ updatePost(id, data)
├─ deletePost(id)
└─ getPostsByCategory(cat)

PostView:
├─ renderPostList()
├─ renderPostDetail(post)
├─ renderPostForm()
└─ renderCategories()

PostController:
├─ handleCreatePost(data)
├─ handleUpdatePost(id, data)
├─ handleDeletePost(id)
└─ handleListPosts(category)
```

## Benefits

**Separation of Concerns**: Each component has one responsibility

**Reusability**: Components can be reused independently

**Testability**: Each component can be tested separately

**Maintainability**: Changes to one component don't affect others

**Team Collaboration**: Different developers work on different layers

**Flexibility**: Easy to swap out any component

## Drawbacks

**Complexity**: More files and classes to manage

**Over-Engineering**: Overkill for very simple applications

**Tight Coupling**: Controller depends on both Model and View

**Learning Curve**: Takes time to understand properly

## MVC Flow
```text
┌────────────────────────────────────────────────────┐
│                  MVC Flow                           │
└────────────────────────────────────────────────────┘

1. User interacts with View
   (clicks button, fills form)
        ↓
2. View sends event to Controller
   (controller.handleSubmit())
        ↓
3. Controller processes request
   (validates, applies business logic)
        ↓
4. Controller updates Model
   (model.save(data))
        ↓
5. Model notifies View of change
   (data updated)
        ↓
6. View re-renders with new data
   (displays updated UI)
        ↓
7. User sees updated interface
```

## MVC vs MVVM vs MVP
```text
┌────────────────────────────────────────────────────┐
│           MVC vs MVVM vs MVP                        │
└────────────────────────────────────────────────────┘

MVC                    MVVM                  MVP
├─ Controller          ├─ ViewModel          ├─ Presenter
├─ Handles input       ├─ Two-way binding    ├─ Handles all logic
├─ Selects View        ├─ View updates auto  ├─ Updates View
├─ View knows Model    ├─ View independent   ├─ View independent
└─ Web frameworks      └─ Modern SPAs        └─ Mobile apps

MVC → Traditional web apps (Express, Django)
MVVM → Modern SPAs (Angular, Vue)
MVP → Mobile apps (Android)
```

## Common Frameworks Using MVC
```text
┌────────────────────────────────────────────────────┐
│        Frameworks Using MVC                         │
└────────────────────────────────────────────────────┘

Backend
├─ Express.js (Node.js)
├─ Django (Python)
├─ Ruby on Rails
├─ Spring MVC (Java)
└─ Laravel (PHP)

Frontend
├─ Backbone.js
├─ AngularJS (1.x)
└─ Ember.js
```

## Implementation Example
```javascript
// Model
class TodoModel {
    constructor() {
        this.todos = [];
    }
    
    addTodo(text) {
        const todo = { id: Date.now(), text, done: false };
        this.todos.push(todo);
        return todo;
    }
    
    toggleTodo(id) {
        const todo = this.todos.find(t => t.id === id);
        if (todo) todo.done = !todo.done;
    }
    
    deleteTodo(id) {
        this.todos = this.todos.filter(t => t.id !== id);
    }
    
    getTodos() {
        return this.todos;
    }
}

// View
class TodoView {
    constructor() {
        this.container = document.getElementById('todo-list');
    }
    
    render(todos) {
        this.container.innerHTML = todos.map(todo => `
            <div class="todo ${todo.done ? 'done' : ''}">
                <span>${todo.text}</span>
                <button class="toggle" data-id="${todo.id}">✓</button>
                <button class="delete" data-id="${todo.id}">✗</button>
            </div>
        `).join('');
    }
    
    showError(message) {
        console.error(message);
    }
}

// Controller
class TodoController {
    constructor(model, view) {
        this.model = model;
        this.view = view;
    }
    
    handleAdd(text) {
        if (!text) {
            this.view.showError("Text required");
            return;
        }
        this.model.addTodo(text);
        this.updateView();
    }
    
    handleToggle(id) {
        this.model.toggleTodo(id);
        this.updateView();
    }
    
    handleDelete(id) {
        this.model.deleteTodo(id);
        this.updateView();
    }
    
    updateView() {
        this.view.render(this.model.getTodos());
    }
}

// Initialize
const model = new TodoModel();
const view = new TodoView();
const controller = new TodoController(model, view);
```text

## Best Practices

**Thin Controllers**: Keep logic minimal in controllers

**Fat Models**: Business logic belongs in model

**Dumb Views**: Views should only display data

**Clear Boundaries**: Don't mix responsibilities

**Consistent Naming**: Use clear, descriptive names

**Error Handling**: Handle errors at controller level

**Data Validation**: Validate in model or controller

## Common Mistakes
```
❌ Business logic in View
└─ View should only render

❌ Database calls in Controller
└─ Use Repository or Model for data

❌ Fat Controller
└─ Move logic to Model or Service

❌ View directly accessing Model
└─ All data flows through Controller

❌ Skipping validation
└─ Always validate input data
```text

## Pros and Cons Summary
```
✅ Pros
├─ Clean separation of concerns
├─ Easy to test each component
├─ Reusable components
├─ Team collaboration friendly
├─ Maintainable codebase
└─ Industry standard pattern

❌ Cons
├─ More files to manage
├─ Overkill for simple apps
├─ Controller can become complex
├─ Learning curve
└─ Tight coupling in Controller
```sql

## Key Takeaways

- **Model**: Data and business logic
- **View**: User interface and display
- **Controller**: Handles input and coordinates
- **Separates concerns** for maintainability
- **Industry standard** for web applications
- **Use when**: Building medium to large applications
- **Don't use when**: Very simple single-page apps

**Remember**: MVC is about separating your application into three focused layers. Model handles data, View handles display, and Controller handles user interaction. Each component should focus on its role without knowing unnecessary details about others. This separation makes your code cleaner, testable, and easier to maintain.

---
# Dependency Injection Pattern

Dependency Injection (DI) is a technique where an object receives its dependencies from outside rather than creating them internally.

## What is Dependency Injection?

**Dependency Injection**: Provide dependencies to objects from outside instead of letting them create their own.

**Core Idea**: Don't create what you need, receive it

Think of a **restaurant kitchen**:
- Chef doesn't buy ingredients (create dependencies)
- Kitchen manager provides ingredients (injects dependencies)
- Chef just cooks with what's provided
- Easy to swap ingredients

## Problem It Solves

**Without DI**:
```
Classes create their own dependencies:

class OrderService {
    constructor() {
        // Creates own dependencies internally
        this.database = new MySQLDatabase();
        this.logger = new FileLogger();
        this.emailService = new EmailService();
    }
    
    processOrder(order) {
        this.logger.log("Processing order");
        this.database.save(order);
        this.emailService.send(order);
    }
}

// Tightly coupled
// Hard to test
// Can't swap implementations
```text

**With DI**:
```
Dependencies provided from outside:

class OrderService {
    constructor(database, logger, emailService) {
        // Receives dependencies
        this.database = database;
        this.logger = logger;
        this.emailService = emailService;
    }
    
    processOrder(order) {
        this.logger.log("Processing order");
        this.database.save(order);
        this.emailService.send(order);
    }
}

// Loosely coupled
// Easy to test
// Easy to swap implementations
```text

## When to Use DI

**Use When**:
- Classes have external dependencies
- Want to make code testable
- Need to swap implementations
- Want loose coupling
- Building medium to large applications

**Don't Use When**:
- Simple applications with few dependencies
- Dependencies never change
- Adds unnecessary complexity

## Types of Dependency Injection

### 1. Constructor Injection
```
Dependencies passed through constructor:

class UserService {
    constructor(userRepository, logger) {
        this.userRepo = userRepository;
        this.logger = logger;
    }
}

// Most recommended approach
// Dependencies clear from constructor
// All dependencies available immediately
```text

### 2. Method/Setter Injection
```
Dependencies set through methods:

class UserService {
    setRepository(repository) {
        this.userRepo = repository;
    }
    
    setLogger(logger) {
        this.logger = logger;
    }
}

// Dependencies optional
// Can change after creation
// Less clear than constructor
```text

### 3. Property Injection
```
Dependencies set directly on properties:

class UserService {
    // Set directly
    userService.repository = new UserRepository();
    userService.logger = new Logger();
}

// Simplest approach
// Less control over injection
// Can be set anytime
```text

## Structure
```
┌──────────────┐
│   Client     │ (Service that needs dependency)
├──────────────┤
│ - dependency │
├──────────────┤
│ + operation()│
└──────△───────┘
       │
       │ receives
       │
┌──────┴───────┐
│  Interface   │ (What client expects)
├──────────────┤
│ + method()   │
└──────△───────┘
       │
   ┌───┴────────┐
   │            │
┌──┴──────┐ ┌──┴──────┐
│ImplA    │ │ImplB    │ (Concrete implementations)
└─────────┘ └─────────┘
       │
       │ created by
       │
┌──────┴───────┐
│  DI Container│ (Optional - manages creation)
└──────────────┘
```text

## Real-World Examples

### 1. Payment Processing
```
// Interface
class PaymentGateway {
    pay(amount) { }
}

// Implementations
class StripeGateway extends PaymentGateway {
    pay(amount) { /* Stripe logic */ }
}

class PayPalGateway extends PaymentGateway {
    pay(amount) { /* PayPal logic */ }
}

// Service receives dependency
class CheckoutService {
    constructor(paymentGateway) {
        this.payment = paymentGateway;
    }
    
    checkout(amount) {
        this.payment.pay(amount);
    }
}

// Inject from outside
const checkout = new CheckoutService(new StripeGateway());

// Easy to switch
const checkout2 = new CheckoutService(new PayPalGateway());
```text

### 2. Notification System
```
class NotificationService {
    constructor(sender) {
        this.sender = sender;
    }
    
    notify(message) {
        this.sender.send(message);
    }
}

// Different senders injected
const emailService = new NotificationService(new EmailSender());
const smsService = new NotificationService(new SmsSender());
const pushService = new NotificationService(new PushSender());
```text

### 3. Database Access
```
class UserRepository {
    constructor(database) {
        this.db = database;
    }
    
    findById(id) {
        return this.db.query(`SELECT * FROM users WHERE id = ?`, [id]);
    }
}

// Inject different databases
const mysqlRepo = new UserRepository(new MySQLDatabase());
const mongoRepo = new UserRepository(new MongoDatabase());

// For testing
const testRepo = new UserRepository(new MockDatabase());
```text

## DI Container
```
Container manages object creation and injection:

class DIContainer {
    constructor() {
        this.services = new Map();
    }
    
    // Register service
    register(name, factory) {
        this.services.set(name, factory);
    }
    
    // Resolve service
    resolve(name) {
        const factory = this.services.get(name);
        return factory(this);
    }
}

// Register services
const container = new DIContainer();
container.register('logger', () => new FileLogger());
container.register('database', () => new MySQLDatabase());
container.register('userRepo', (c) => new UserRepository(c.resolve('database')));
container.register('userService', (c) => new UserService(
    c.resolve('userRepo'),
    c.resolve('logger')
));

// Resolve
const userService = container.resolve('userService');
// All dependencies automatically injected
```text

## Benefits

**Loose Coupling**: Classes don't create own dependencies

**Testability**: Easy to inject mocks for testing

**Flexibility**: Swap implementations without code changes

**Single Responsibility**: Classes focus on their own logic

**Reusability**: Components reusable across application

**Maintainability**: Changes isolated to specific components

## Drawbacks

**Complexity**: More setup required

**Indirection**: Harder to trace dependency creation

**Over-Engineering**: Overkill for simple applications

**Container Dependency**: May couple to DI framework

## Testing with DI
```
// Real implementation
class RealEmailService {
    send(message) {
        // Actually sends email
    }
}

// Mock for testing
class MockEmailService {
    constructor() {
        this.sentMessages = [];
    }
    
    send(message) {
        this.sentMessages.push(message);
    }
}

// Test with mock
const mockEmail = new MockEmailService();
const service = new NotificationService(mockEmail);
service.notify("Hello");

// Verify
console.log(mockEmail.sentMessages); // ["Hello"]
```text

## DI vs Service Locator
```
┌────────────────────────────────────────────────────┐
│         DI vs Service Locator                       │
└────────────────────────────────────────────────────┘

Dependency Injection          Service Locator
├─ Dependencies explicit      ├─ Dependencies hidden
├─ Injected from outside      ├─ Fetched internally
├─ Easy to test               ├─ Hard to test
├─ Clear dependency graph     ├─ Hidden dependencies
├─ Recommended approach       ├─ Anti-pattern
└─ Constructor makes clear    └─ Hides what's needed

// DI (Good)
class Service {
    constructor(dependency) {  // Clear what's needed
        this.dep = dependency;
    }
}

// Service Locator (Bad)
class Service {
    constructor() {
        this.dep = container.get('dep');  // Hidden
    }
}
```text

## Common Use Cases
```
┌────────────────────────────────────────────────────┐
│      Common DI Applications                         │
└────────────────────────────────────────────────────┘

Database Access
└─ Inject different database connections

Logging
└─ Inject different loggers

Payment Processing
└─ Inject payment gateways

Email/SMS
└─ Inject notification services

Authentication
└─ Inject auth providers

Cache
└─ Inject cache implementations

Testing
└─ Inject mocks and stubs
```text

## Best Practices

**Constructor Injection First**: Prefer constructor injection

**Depend on Interfaces**: Inject interfaces, not concrete classes

**Single Responsibility**: One dependency per interface

**Limit Dependencies**: Don't inject too many dependencies

**Use Container**: For large apps, use DI container

**Document Dependencies**: Make dependencies clear

**Avoid Circular Dependencies**: Watch for circular injection

## Pros and Cons Summary
```
✅ Pros
├─ Loose coupling
├─ Easy testing
├─ Flexible implementations
├─ Single Responsibility
├─ Open/Closed Principle
├─ Dependency Inversion Principle
└─ Reusable components

❌ Cons
├─ More complex setup
├─ Extra indirection
├─ Overkill for simple apps
├─ Container can be confusing
└─ Requires good interface design
```text

## Key Takeaways

- **Provide dependencies externally** instead of creating internally
- **Three types**: Constructor, Method, Property injection
- **Constructor injection** is most recommended
- **Makes code testable** with mock dependencies
- **Enables flexibility** to swap implementations
- **Use when**: Want testable, loosely coupled code
- **Don't use when**: Simple app with few dependencies

**Remember**: Dependency Injection is about letting objects receive what they need rather than finding or creating it themselves. It's the foundation of loosely coupled, testable code. Constructor injection is the cleanest approach - it makes dependencies obvious and ensures they're available when needed.

---

# Specification Pattern

The Specification pattern defines business rules as combinable objects. It allows you to combine conditions using logical operators to create complex filtering and validation rules.

## What is Specification Pattern?

**Specification Pattern**: Encapsulates business rules as reusable, combinable objects.

**Core Idea**: Rules as objects that can be combined

Think of a **job posting filter**:
- Remote work
- Salary > $100k
- 5+ years experience
- Combine: Remote AND Salary > $100k AND Experience > 5
- Each condition is reusable and combinable

## Problem It Solves

**Without Specification**:
```
Complex conditional logic scattered everywhere:

function getEligibleProducts(products) {
    return products.filter(product => {
        return product.price > 100 &&
               product.price < 1000 &&
               product.inStock === true &&
               product.category === 'electronics' &&
               product.rating >= 4;
    });
}

// Hard to reuse conditions
// Scattered validation logic
// Difficult to maintain
// Can't combine rules easily
```text

**With Specification**:
```
Rules as reusable objects:

const priceRange = new PriceRangeSpec(100, 1000);
const inStock = new InStockSpec();
const electronics = new CategorySpec('electronics');
const highRated = new MinRatingSpec(4);

// Combine rules
const eligible = priceRange
    .and(inStock)
    .and(electronics)
    .and(highRated);

// Use anywhere
const results = products.filter(p => eligible.isSatisfiedBy(p));

// Clean, reusable, combinable
```text

## When to Use Specification

**Use When**:
- Business rules need to be combined
- Same conditions used in multiple places
- Rules change frequently
- Need complex filtering or validation
- Want reusable business logic

**Don't Use When**:
- Simple single conditions
- Rules never change or combine
- Adds unnecessary complexity
- Simple if-else is sufficient

## Structure
```
┌──────────────────┐
│  Specification   │ (Abstract/Interface)
├──────────────────┤
│ + isSatisfiedBy()│
│ + and(spec)      │
│ + or(spec)       │
│ + not()          │
└────────△─────────┘
         │
    ┌────┼────────────────┐
    │    │                │
┌───┴──┐ ┌───┴──┐   ┌────┴─────┐
│Concrete│ │Concrete│   │Composite │
│Spec A│ │Spec B│   │Spec      │
├──────┤ ├──────┤   ├──────────┤
│+isSat│ │+isSat│   │- left    │
└──────┘ └──────┘   │- right   │
                    │- operator│
                    └──────────┘
```text

## Key Components
```
┌────────────────────────────────────────────────────┐
│       Specification Pattern Components              │
└────────────────────────────────────────────────────┘

Base Specification
└─ isSatisfiedBy(item): Check if item meets criteria
└─ and(spec): Combine with AND logic
└─ or(spec): Combine with OR logic
└─ not(): Negate specification

Concrete Specifications
└─ Implement single business rule
└─ Reusable across application

Composite Specifications
└─ AndSpec: Both specs must be true
└─ OrSpec: Either spec must be true
└─ NotSpec: Negates a specification
```text

## Logical Operators

### AND Specification
```
Both conditions must be true:

inStock AND priceAbove100

Item must be:
└─ In stock
└─ Price above $100

Both must be satisfied
```text

### OR Specification

### NOT Specification
```
Negates a condition:

NOT outOfStock = inStock

Reverses the result of specification
```text

## Real-World Examples

### 1. Product Filtering
```
// Individual specifications
class InStockSpec {
    isSatisfiedBy(product) {
        return product.stock > 0;
    }
}

class PriceRangeSpec {
    constructor(min, max) {
        this.min = min;
        this.max = max;
    }
    
    isSatisfiedBy(product) {
        return product.price >= this.min && product.price <= this.max;
    }
}

class CategorySpec {
    constructor(category) {
        this.category = category;
    }
    
    isSatisfiedBy(product) {
        return product.category === this.category;
    }
}

class MinRatingSpec {
    constructor(minRating) {
        this.minRating = minRating;
    }
    
    isSatisfiedBy(product) {
        return product.rating >= this.minRating;
    }
}

// Combine and use
const spec = new InStockSpec()
    .and(new PriceRangeSpec(50, 500))
    .and(new CategorySpec('electronics'))
    .and(new MinRatingSpec(4));

const filtered = products.filter(p => spec.isSatisfiedBy(p));
```text

### 2. User Validation
```
Specifications:
├─ AgeAboveSpec(minAge)
│   └─ user.age >= minAge
├─ HasEmailSpec()
│   └─ user.email !== null
├─ ActiveAccountSpec()
│   └─ user.status === 'active'
└─ VerifiedSpec()
    └─ user.verified === true

// Combine for eligibility
const eligibleUser = new AgeAboveSpec(18)
    .and(new HasEmailSpec())
    .and(new ActiveAccountSpec())
    .and(new VerifiedSpec());

// Use in different places
users.filter(u => eligibleUser.isSatisfiedBy(u));
```text

### 3. Order Processing Rules
```
Specifications:
├─ MinOrderAmountSpec(amount)
│   └─ order.total >= amount
├─ HasValidItemsSpec()
│   └─ all items are in stock
├─ ValidPaymentSpec()
│   └─ payment method is valid
└─ ShippableSpec()
    └─ all items can be shipped

// Can process order if:
const canProcess = new MinOrderAmountSpec(10)
    .and(new HasValidItemsSpec())
    .and(new ValidPaymentSpec());

// Can ship order if:
const canShip = new HasValidItemsSpec()
    .and(new ShippableSpec());

// Reuse specifications in different contexts
```text

### 4. Discount Eligibility
```
Specifications:
├─ NewCustomerSpec()
│   └─ customer.orderCount === 0
├─ LoyalCustomerSpec(minOrders)
│   └─ customer.orderCount >= minOrders
├─ SeasonalSpec(season)
│   └─ current season matches
└─ MinPurchaseSpec(amount)
    └─ order.total >= amount

// New customer discount
const newCustomerDiscount = new NewCustomerSpec()
    .and(new MinPurchaseSpec(50));

// Loyal customer discount
const loyalDiscount = new LoyalCustomerSpec(10)
    .or(new SeasonalSpec('summer'));

// Apply appropriate discount
if (newCustomerDiscount.isSatisfiedBy(customer)) {
    applyDiscount(10);
} else if (loyalDiscount.isSatisfiedBy(customer)) {
    applyDiscount(15);
}
```text

### 5. Job Candidate Filtering
```
Specifications:
├─ ExperienceSpec(years)
│   └─ candidate.experience >= years
├─ SkillSpec(skill)
│   └─ candidate.skills.includes(skill)
├─ LocationSpec(location)
│   └─ candidate.location === location
└─ AvailableSpec()
    └─ candidate.available === true

// Senior developer search
const seniorDev = new ExperienceSpec(5)
    .and(new SkillSpec('JavaScript'))
    .and(new SkillSpec('React'))
    .and(new AvailableSpec());

// Remote OR local
const location = new LocationSpec('NYC')
    .or(new RemoteSpec());

// Combined
const idealCandidate = seniorDev.and(location);
```sql

## Benefits

**Reusability**: Same rules used in multiple places

**Combinability**: Build complex rules from simple ones

**Readability**: Rules are self-documenting

**Maintainability**: Change rules in one place

**Testability**: Test individual specifications easily

**Single Responsibility**: Each specification has one rule

## Drawbacks

**Complexity**: Many small classes

**Over-Engineering**: Overkill for simple conditions

**Performance**: Chain of checks can be slow

**Learning Curve**: Takes time to understand combining

## Specification vs Strategy Pattern
```
┌────────────────────────────────────────────────────┐
│         Specification vs Strategy                   │
└────────────────────────────────────────────────────┘

Specification              Strategy
├─ Combinable rules        ├─ Interchangeable algorithms
├─ Boolean logic (AND/OR)  ├─ No combining
├─ Filtering/Validation    ├─ Execution logic
├─ Returns true/false      ├─ Returns result
├─ Rules composition       ├─ Algorithm selection
└─ Intent: Check condition └─ Intent: Do action
```text

## Common Use Cases
```
┌────────────────────────────────────────────────────┐
│      Common Specification Applications              │
└────────────────────────────────────────────────────┘

Product Filtering
└─ E-commerce search filters

User Validation
└─ Registration, eligibility checks

Order Processing
└─ Order validation rules

Discount Rules
└─ Promotional eligibility

Access Control
└─ Permission checking

Report Filtering
└─ Complex report criteria

Job Matching
└─ Candidate filtering

Loan Approval
└─ Eligibility criteria
```text

## Best Practices

**Single Rule Per Spec**: Keep specifications focused

**Clear Naming**: Name specs after business rules

**Immutable**: Make specifications immutable after creation

**Document Combinations**: Explain why rules are combined

**Test Individual Specs**: Unit test each specification

**Reuse Aggressively**: Create specs for repeated conditions

**Keep Simple**: Don't over-combine specifications

## Pros and Cons Summary
```
✅ Pros
├─ Reusable business rules
├─ Combinable with AND/OR/NOT
├─ Clean, readable code
├─ Easy to test
├─ Single Responsibility Principle
├─ Easy to add new rules
└─ Self-documenting

❌ Cons
├─ Many small classes
├─ Over-engineering risk
├─ Performance overhead
├─ Complex for simple cases
└─ Requires good naming
```

## Key Takeaways

- **Encapsulates business rules** as objects
- **Combine rules** using AND, OR, NOT operators
- **Reusable** across different parts of application
- **Clean and readable** rule composition
- **Easy to test** individual specifications
- **Use when**: Complex combinable business rules
- **Don't use when**: Simple single conditions

**Remember**: Specification pattern is about turning business rules into reusable, combinable objects. It's perfect for filtering, validation, and eligibility checks where conditions need to be combined and reused. Think of each specification as a building block that can be combined with others to create complex rules.


# Game Loop Pattern

The Game Loop pattern continuously processes user input, updates game state, and renders graphics in a fixed-time loop to create smooth gameplay.

## What is Game Loop Pattern?

**Game Loop Pattern**: Runs game logic repeatedly in a continuous loop.

**Core Idea**: Update and render the game world continuously

Think of a **film projector**:
- Shows frames continuously (24 fps)
- Each frame slightly different
- Creates illusion of motion
- Runs as long as film plays

## Problem It Solves

**Without Game Loop**:
```
Event-driven approach doesn't work for games:

button.onClick = movePlayer;
// Game only responds to events
// No continuous world updates
// Enemies don't move automatically
// Physics don't apply continuously
```

**With Game Loop**:
```
Continuous updates:

while (gameRunning) {
    handleInput();      // Process player input
    update(deltaTime);  // Update game state
    render();           // Draw frame
}

// World always updating
// Smooth continuous motion
// Physics always applying
```

## When to Use Game Loop

**Use When**:
- Building games or simulations
- Need continuous updates
- Real-time rendering required
- Physics or animation needed

**Don't Use When**:
- Event-driven apps (UI apps, websites)
- No continuous updates needed
- Simple turn-based logic

## Basic Structure
```
┌────────────────────────────────────────────────────┐
│              Game Loop Structure                    │
└────────────────────────────────────────────────────┘

Initialize Game
    ↓
┌─────────────────────┐
│   Game Loop         │
│                     │
│   processInput()    │ ← Handle keyboard/mouse
│         ↓           │
│   update(dt)        │ ← Update game state
│         ↓           │
│   render()          │ ← Draw to screen
│         ↓           │
│   if (!quit)        │
│     continue loop   │
└─────────────────────┘
    ↓
Cleanup and Exit
```

## Real-World Example
```javascript
class Game {
    constructor() {
        this.running = true;
        this.lastTime = Date.now();
        this.entities = [];
    }
    
    // Main game loop
    run() {
        while (this.running) {
            const currentTime = Date.now();
            const deltaTime = (currentTime - this.lastTime) / 1000;
            this.lastTime = currentTime;
            
            this.processInput();
            this.update(deltaTime);
            this.render();
        }
    }
    
    processInput() {
        // Handle keyboard, mouse, gamepad input
        if (keyboard.isPressed('ESC')) {
            this.running = false;
        }
        if (keyboard.isPressed('SPACE')) {
            this.player.jump();
        }
    }
    
    update(deltaTime) {
        // Update all entities
        this.entities.forEach(entity => {
            entity.update(deltaTime);
        });
        
        // Check collisions
        this.checkCollisions();
        
        // Update physics
        this.physics.update(deltaTime);
    }
    
    render() {
        // Clear screen
        this.screen.clear();
        
        // Draw all entities
        this.entities.forEach(entity => {
            entity.draw(this.screen);
        });
        
        // Display frame
        this.screen.present();
    }
}

const game = new Game();
game.run();
```

## Time Management

### Fixed Time Step
```
Update at fixed intervals (e.g., 60 updates/sec):

const FIXED_TIME_STEP = 1/60;
let accumulator = 0;

while (running) {
    const frameTime = getElapsedTime();
    accumulator += frameTime;
    
    while (accumulator >= FIXED_TIME_STEP) {
        update(FIXED_TIME_STEP);
        accumulator -= FIXED_TIME_STEP;
    }
    
    render();
}

// Consistent physics
// Deterministic gameplay
```

### Variable Time Step
```
Update based on actual elapsed time:

while (running) {
    const deltaTime = getElapsedTime();
    update(deltaTime);
    render();
}

// Simpler implementation
// Can be inconsistent
```

## Benefits

**Continuous Updates**: Game world always alive

**Smooth Animation**: Consistent frame rates

**Decoupled Logic**: Input, update, render separated

**Predictable Timing**: Control update frequency

## Drawbacks

**CPU Intensive**: Always running

**Battery Drain**: Constant processing

**Complex Timing**: Frame rate management tricky

## Key Takeaways

- **Runs continuously** in a loop
- **Three phases**: Input → Update → Render
- **Delta time** for consistent movement
- **Essential for games** and simulations
- **Use when**: Real-time continuous updates needed

---

# Thread Pool Pattern

The Thread Pool pattern manages a pool of worker threads that execute tasks from a queue, avoiding the overhead of creating new threads for each task.

## What is Thread Pool Pattern?

**Thread Pool Pattern**: Reuses a fixed number of threads to execute many tasks.

**Core Idea**: Don't create/destroy threads repeatedly, reuse them

Think of a **restaurant kitchen**:
- Fixed number of chefs (threads)
- Orders keep coming (tasks)
- Chefs take next order when free
- Don't hire/fire chefs for each order

## Problem It Solves

**Without Thread Pool**:
```
Create new thread for each task:

for (task in tasks) {
    thread = new Thread(task);
    thread.start();
    // Creates many threads
    // Thread creation overhead
    // Resource exhaustion
}

// Expensive thread creation
// Unlimited threads
// System overload risk
```

**With Thread Pool**:
```
Reuse threads from pool:

threadPool = new ThreadPool(size: 10);

for (task in tasks) {
    threadPool.submit(task);
    // Reuses existing threads
    // Limited concurrent threads
    // Efficient resource use
}

// No creation overhead
// Controlled concurrency
// Better performance
```

## When to Use Thread Pool

**Use When**:
- Many short-lived tasks
- Tasks are independent
- Want to limit concurrent threads
- Need efficient resource usage

**Don't Use When**:
- Tasks are long-running
- Single-threaded is sufficient
- Tasks have dependencies

## Structure
```
┌────────────────────────────────────────────────────┐
│           Thread Pool Structure                     │
└────────────────────────────────────────────────────┘

    Tasks submitted
         ↓
┌─────────────────┐
│   Task Queue    │
│  [T1][T2][T3]   │
└────────┬────────┘
         │ assigned to
         ↓
┌─────────────────┐
│  Thread Pool    │
│                 │
│  Thread 1 ──────┼── executing task
│  Thread 2 ──────┼── executing task
│  Thread 3 ──────┼── idle
│  Thread 4 ──────┼── idle
└─────────────────┘
```

## Simple Implementation
```javascript
class ThreadPool {
    constructor(size) {
        this.size = size;
        this.tasks = [];
        this.workers = [];
        this.activeCount = 0;
        
        // Create worker threads
        for (let i = 0; i < size; i++) {
            this.workers.push(this.createWorker());
        }
    }
    
    createWorker() {
        const worker = {
            busy: false,
            execute: async (task) => {
                this.activeCount++;
                worker.busy = true;
                
                try {
                    await task();
                } finally {
                    worker.busy = false;
                    this.activeCount--;
                    this.processNext();
                }
            }
        };
        return worker;
    }
    
    submit(task) {
        this.tasks.push(task);
        this.processNext();
    }
    
    processNext() {
        if (this.tasks.length === 0) return;
        
        // Find idle worker
        const worker = this.workers.find(w => !w.busy);
        if (worker) {
            const task = this.tasks.shift();
            worker.execute(task);
        }
    }
    
    shutdown() {
        // Wait for active tasks to complete
        // Then terminate all workers
    }
}

// Usage
const pool = new ThreadPool(4);

// Submit tasks
for (let i = 0; i < 100; i++) {
    pool.submit(() => processData(i));
}
// Only 4 threads handle all 100 tasks
```

## Benefits

**Performance**: No thread creation overhead

**Resource Control**: Limit concurrent threads

**Efficiency**: Thread reuse

**Scalability**: Handle many tasks with few threads

**Queue Management**: Built-in task queuing

## Drawbacks

**Complexity**: More complex than simple threading

**Overhead**: Pool management overhead

**Deadlock Risk**: If pool size too small

**Memory**: Threads stay in memory

## Common Use Cases
```
┌────────────────────────────────────────────────────┐
│       Common Thread Pool Applications               │
└────────────────────────────────────────────────────┘

Web Servers
└─ Handle incoming requests

Database Connections
└─ Execute queries concurrently

Background Jobs
└─ Process tasks asynchronously

Image Processing
└─ Process multiple images

File Operations
└─ Read/write multiple files

Network Operations
└─ Handle multiple connections
```

## Key Takeaways

- **Reuses threads** instead of creating new ones
- **Fixed pool size** limits concurrency
- **Task queue** holds pending work
- **Better performance** than creating threads per task
- **Use when**: Many short-lived concurrent tasks

---

# Producer-Consumer Pattern

The Producer-Consumer pattern decouples production of data from its consumption using a shared buffer or queue between producers and consumers.

## What is Producer-Consumer Pattern?

**Producer-Consumer Pattern**: Producers create data, consumers process it, queue buffers between them.

**Core Idea**: Separate data production from data processing

Think of a **factory assembly line**:
- Workers produce parts (producers)
- Conveyor belt holds parts (buffer/queue)
- Other workers assemble parts (consumers)
- Production and assembly happen independently

## Problem It Solves

**Without Producer-Consumer**:
```
Direct coupling - producer waits for consumer:

producer() {
    data = generateData();
    consumer.process(data);  // Must wait
    // Blocks until consumer finishes
}

// Producer and consumer tightly coupled
// No parallel processing
// Inefficient if speeds differ
```

**With Producer-Consumer**:
```
Queue decouples them:

// Producer
producer() {
    data = generateData();
    queue.add(data);  // Doesn't wait
    // Keep producing
}

// Consumer
consumer() {
    data = queue.take();  // Process when available
    process(data);
}

// Independent speeds
// Parallel processing
// Better throughput
```

## When to Use Producer-Consumer

**Use When**:
- Production and consumption at different rates
- Want to decouple producer from consumer
- Need buffering between stages
- Parallel processing beneficial

**Don't Use When**:
- Direct communication is simpler
- No speed difference
- Single-threaded is sufficient

## Structure
```
┌────────────────────────────────────────────────────┐
│        Producer-Consumer Structure                  │
└────────────────────────────────────────────────────┘

Producer(s)          Buffer/Queue         Consumer(s)
    │                    │                     │
    │ produces           │                     │
    ├───────────────────>│                     │
    │                    │                     │
    │                    │  consumes           │
    │                    ├────────────────────>│
    │                    │                     │
    ├───────────────────>│                     │
    │                    ├────────────────────>│
    │                    │                     │
 Multiple            Shared Queue          Multiple
 producers            (Thread-safe)        consumers
```

## Simple Implementation
```javascript
class ProducerConsumer {
    constructor(bufferSize = 10) {
        this.queue = [];
        this.maxSize = bufferSize;
        this.running = true;
    }
    
    // Producer
    async produce(item) {
        while (this.queue.length >= this.maxSize) {
            // Wait if queue is full
            await this.sleep(10);
        }
        this.queue.push(item);
        console.log(`Produced: ${item}, Queue: ${this.queue.length}`);
    }
    
    // Consumer
    async consume() {
        while (this.queue.length === 0) {
            // Wait if queue is empty
            if (!this.running) return null;
            await this.sleep(10);
        }
        const item = this.queue.shift();
        console.log(`Consumed: ${item}, Queue: ${this.queue.length}`);
        return item;
    }
    
    sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
}

// Usage
const pc = new ProducerConsumer(5);

// Start producer
async function producer() {
    for (let i = 0; i < 20; i++) {
        await pc.produce(`Item-${i}`);
        await pc.sleep(Math.random() * 100);
    }
}

// Start consumer
async function consumer() {
    for (let i = 0; i < 20; i++) {
        await pc.consume();
        await pc.sleep(Math.random() * 150);
    }
}

// Run both concurrently
Promise.all([producer(), consumer()]);
```

## Real-World Examples

### 1. Log Processing
```
Producers: Multiple services generating logs
Queue: Log message buffer
Consumers: Log processors writing to database/file

Services produce logs at varying rates
Consumers process at their own pace
Queue prevents log loss
```

### 2. Image Processing Pipeline
```
Producer: Image upload service
Queue: Image task queue
Consumer: Image processing workers

Users upload images
Queue holds pending images
Workers resize/optimize images
```

### 3. Order Processing
```
Producer: Order placement system
Queue: Order queue
Consumer: Order fulfillment service

Orders created continuously
Queue buffers during peak times
Fulfillment processes steadily
```

## Benefits

**Decoupling**: Producers and consumers independent

**Buffering**: Queue smooths rate differences

**Scalability**: Add more producers/consumers easily

**Resilience**: Queue prevents data loss

**Parallel Processing**: Producers and consumers run concurrently

## Drawbacks

**Queue Management**: Need to manage queue size

**Memory**: Queue consumes memory

**Complexity**: Synchronization needed

**Latency**: Queuing adds delay

## Common Use Cases
```
┌────────────────────────────────────────────────────┐
│      Common Producer-Consumer Applications          │
└────────────────────────────────────────────────────┘

Logging Systems
└─ Services produce logs, processors consume

Message Queues
└─ Publishers produce, subscribers consume

Data Pipelines
└─ ETL processes

Event Processing
└─ Event producers and handlers

Task Scheduling
└─ Job queue systems

Download Managers
└─ Download tasks

Print Spooling
└─ Print job queue
```

## Key Takeaways

- **Decouples** data production from processing
- **Queue/buffer** between producers and consumers
- **Independent speeds** for production and consumption
- **Enables parallelism** and better throughput
- **Use when**: Different production/consumption rates
- **Don't use when**: Direct communication is simpler

**Remember**: Producer-Consumer pattern is about separating concerns - let producers focus on creating data and consumers focus on processing it, with a queue in between to handle timing differences and enable parallel operation.

---

# How to Approach LLD Interviews

LLD interviews assess your ability to design clean, maintainable, and extensible code. Here's a structured approach to tackle them.

## The PEDAC Framework

```text
P - Problem Understanding
E - Examples and Edge Cases
D - Data Structures and Classes
A - Algorithm and Flow
C - Code Implementation
```

## Step-by-Step Approach

### 1. Clarify Requirements (5 min)
```text
Ask about:
├─ Core functionality (what must work)
├─ Scale (users, data volume)
├─ Constraints (memory, time)
└─ Edge cases (failures, limits)
```

### 2. Identify Core Entities (5 min)
```text
Extract nouns from requirements:
├─ User, Account, Order
├─ What attributes do they have?
└─ What actions can they perform?
```

### 3. Define Relationships (5 min)
```mermaid
flowchart LR
  User -->|places| Order
  Order -->|contains| Item
  Item -->|belongs to| Category
```

### 4. Apply Design Patterns (5 min)
```text
Match problems to patterns:
├─ Object creation? → Factory, Builder
├─ One instance? → Singleton
├─ Notify changes? → Observer
└─ Multiple algorithms? → Strategy
```

### 5. Write Clean Code (remaining time)
- Start with interfaces
- Implement core classes
- Add edge case handling

## Common Interview Problems

| Problem | Key Patterns | Focus Areas |
|---------|--------------|-------------|
| Parking Lot | Factory, Strategy | Vehicle hierarchy, spot allocation |
| Elevator System | State, Observer | State transitions, scheduling |
| Library Management | Repository, Observer | Book/member management |
| Chess Game | State, Command | Move validation, game rules |
| File System | Composite | Tree structure, permissions |

## Interview Checklist

```text
✅ Asked clarifying questions
✅ Identified core entities
✅ Drew class diagram
✅ Explained relationships
✅ Applied relevant patterns
✅ Handled edge cases
✅ Discussed trade-offs
```

---

# How to Write Clean Code

Clean code is readable, maintainable, and does one thing well. Follow these principles to write code that others (and your future self) will thank you for.

## The Clean Code Principles

```text
READABLE    → Code explains itself
SIMPLE      → No unnecessary complexity
DRY         → Don't Repeat Yourself
TESTABLE    → Easy to verify
MAINTAINABLE → Easy to change
```

## Naming Conventions

### Good vs Bad Names
```javascript
// ❌ Bad
const d = 5;
const arr = [];
function calc(x, y) {}

// ✅ Good
const daysUntilDeadline = 5;
const activeUsers = [];
function calculateTotalPrice(quantity, unitPrice) {}
```

### Naming Rules
```text
Variables → Nouns (user, orderTotal)
Functions → Verbs (getUser, calculateTotal)
Booleans  → is/has/can (isActive, hasPermission)
Classes   → PascalCase nouns (UserService, OrderManager)
Constants → UPPER_SNAKE (MAX_RETRIES, API_URL)
```

## Function Design

### Single Responsibility
```javascript
// ❌ Does too much
function processOrder(order) {
    validate(order);
    calculateTotal(order);
    applyDiscount(order);
    saveToDb(order);
    sendEmail(order);
}

// ✅ Each function does one thing
function processOrder(order) {
    const validated = validateOrder(order);
    const priced = calculateOrderTotal(validated);
    const discounted = applyDiscount(priced);
    saveOrder(discounted);
    notifyCustomer(discounted);
}
```

### Keep Functions Small
```text
Ideal function:
├─ < 20 lines
├─ < 3 parameters
├─ 1 level of abstraction
└─ Does ONE thing
```

## Code Organization

### File Structure
```text
src/
├─ models/       → Data classes
├─ services/     → Business logic
├─ repositories/ → Data access
├─ controllers/  → Request handling
└─ utils/        → Helper functions
```

### Class Structure
```javascript
class OrderService {
    // 1. Constants
    static MAX_ITEMS = 100;
    
    // 2. Constructor
    constructor(repo) {
        this.repo = repo;
    }
    
    // 3. Public methods
    async createOrder(data) { }
    
    // 4. Private methods
    #validateOrder(data) { }
}
```

## Error Handling

```javascript
// ❌ Silent failures
function getUser(id) {
    try {
        return db.find(id);
    } catch (e) {
        return null;
    }
}

// ✅ Explicit errors
function getUser(id) {
    const user = db.find(id);
    if (!user) {
        throw new UserNotFoundError(id);
    }
    return user;
}
```

## Clean Code Checklist

```text
✅ Meaningful names
✅ Small, focused functions
✅ No magic numbers
✅ Consistent formatting
✅ Proper error handling
✅ No dead code
✅ Comments explain "why" not "what"
```

---

# How to Choose Design Patterns

Choosing the right design pattern is about matching problems to proven solutions. Here's a practical guide.

## Pattern Selection Flowchart

```mermaid
flowchart TD
  A[What's the problem?] --> B{Object Creation?}
  B -- Yes --> C{Complex construction?}
  C -- Yes --> D[Builder]
  C -- No --> E{Multiple types?}
  E -- Yes --> F[Factory]
  E -- No --> G{Single instance?}
  G -- Yes --> H[Singleton]
  B -- No --> I{Object Structure?}
  I -- Yes --> J{Add behavior?}
  J -- Yes --> K[Decorator]
  J -- No --> L{Simplify interface?}
  L -- Yes --> M[Facade]
  I -- No --> N{Object Behavior?}
  N -- Yes --> O{Multiple algorithms?}
  O -- Yes --> P[Strategy]
  O -- No --> Q{State changes?}
  Q -- Yes --> R[State]
```

## Quick Reference Guide

| Problem | Pattern | Example |
|---------|---------|---------|
| One global instance | Singleton | Database connection |
| Create objects without specifying class | Factory | Payment processors |
| Complex object construction | Builder | HTTP request builder |
| Add features dynamically | Decorator | Coffee with toppings |
| Simplify complex system | Facade | Video conversion API |
| Incompatible interfaces | Adapter | Legacy system wrapper |
| React to changes | Observer | Event notifications |
| Multiple algorithms | Strategy | Sorting algorithms |
| Object state changes | State | Order status flow |
| Undo/redo operations | Command | Text editor actions |

## Decision Matrix

```text
┌─────────────────────────────────────────────────────┐
│          When to Use Each Pattern                    │
└─────────────────────────────────────────────────────┘

CREATIONAL (Object Creation)
├─ Singleton  → Need exactly one instance
├─ Factory    → Create objects without knowing exact class
├─ Builder    → Object has many optional parameters
└─ Prototype  → Clone existing objects

STRUCTURAL (Object Composition)
├─ Adapter    → Make incompatible interfaces work
├─ Decorator  → Add responsibilities dynamically
├─ Facade     → Simplify complex subsystems
├─ Composite  → Tree structures (files/folders)
└─ Proxy      → Control access to object

BEHAVIORAL (Object Interaction)
├─ Strategy   → Switch algorithms at runtime
├─ Observer   → One-to-many notifications
├─ State      → Object behavior depends on state
├─ Command    → Encapsulate requests as objects
└─ Template   → Define algorithm skeleton
```

## Red Flags: When NOT to Use Patterns

```text
❌ Don't use patterns when:
├─ Simple solution exists
├─ Team doesn't understand the pattern
├─ Pattern adds more complexity than it solves
├─ You're using it just because it's "cool"
└─ YAGNI - You Ain't Gonna Need It
```

## Pattern Combination Tips

```text
Common combinations:
├─ Factory + Singleton (single factory instance)
├─ Strategy + Factory (create strategies dynamically)
├─ Observer + Command (undo with notifications)
├─ Decorator + Factory (create decorated objects)
└─ State + Command (state transitions as commands)
```

## Key Takeaways

- **Start simple** - don't pattern everything
- **Match problem to pattern** - use the flowchart
- **Consider trade-offs** - patterns add complexity
- **Document your choice** - explain why you chose it
- **Refactor into patterns** - don't force patterns early

**Remember**: Design patterns are tools, not goals. The best code is often the simplest code that solves the problem. Use patterns when they genuinely help, not to show off.


