Skip to main content

Design Patterns (Capstone)

Introduction: Architectural Thinking at Scale

You've spent Lessons 1-4 mastering the fundamental tools of object-oriented design: inheritance hierarchies, polymorphism, composition, and special methods. Now comes the moment where these tools become architecture.

Design patterns are reusable solutions to common architectural problems. They're the vocabulary of professional software engineering—when you tell another developer "we'll use the Observer pattern for agent communication," they immediately understand your architecture without you explaining details.

In this capstone lesson, you'll implement four industry-standard patterns in a real AI agent system. Each pattern solves a specific problem:

  • Singleton: Ensure only one manager coordinates all agents
  • Factory: Create different agent types dynamically without hardcoding classes
  • Observer: Enable event-driven agent communication
  • Strategy: Let agents select different decision-making approaches at runtime

By the end, you'll have built a professional multi-agent architecture that integrates all 4 patterns—the kind of system you'd encounter in production AI applications.

Why this matters: Design patterns separate junior developers from architects. Junior developers write code that works. Architects design systems that scale, adapt, and integrate. This lesson transitions you from code-writing to architectural thinking.


Part 1: Singleton Pattern — Global State Done Right

The Problem: Too Many Instances

Imagine you're building an agent management system. Every part of your code needs access to the same agent manager—no duplicates, no inconsistency. How do you ensure only one instance exists?

Loading Python environment...

The Singleton pattern solves this: guarantee exactly one instance, globally accessible.

The Solution: Singleton Implementation

Loading Python environment...

How it works:

  1. __new__() controls instance creation. First call creates instance and saves it in _instance. Subsequent calls return the same instance.
  2. __init__() might be called multiple times (once per reference), so we guard initialization with _initialized flag.
  3. Result: AgentManager() always returns the exact same object, no matter how many times you call it.

🎓 Expert Insight

Singletons are controversial in software engineering. Use for: configuration managers, loggers, connection pools—stateless or simple-state resources. Avoid for: anything that needs different state in tests or multiple independent instances. The controversy exists because global state makes testing and reasoning about code harder. But for true global coordination points (like the agent manager), Singleton is appropriate.

💬 AI Colearning Prompt

"Explain the difference between Singleton pattern and a module-level variable. Why use Singleton instead of just manager = AgentManager() at module level? What problem does Singleton solve that module-level variables don't?"


Part 2: Factory Pattern — Decoupling Object Creation

The Problem: Tight Coupling to Concrete Classes

As your system grows, you have multiple agent types:

Loading Python environment...

This is fragile. Adding a new agent type requires changing this code everywhere. The Factory pattern decouples object creation from usage.

The Solution: Factory Implementation

Loading Python environment...

How it works:

  1. Agent is an abstract interface. Concrete agents (ChatAgent, CodeAgent, DataAgent) implement it.
  2. AgentFactory.create_agent() takes a type string and returns the appropriate agent.
  3. The registry pattern allows new agent types to be added without modifying the factory method.
  4. Code that uses agents doesn't care what concrete type it is—it just calls the Agent interface.

🚀 CoLearning Challenge

Ask your AI Co-Teacher:

"Show me how to extend this factory with a registry pattern where agents can self-register their types. Then demonstrate creating a custom RAGAgent that automatically registers itself without modifying AgentFactory code."

Expected Outcome: You'll understand how to decouple class registration from class creation, enabling true plugin-like architecture.

🎓 Expert Insight

The Factory pattern is critical in AI systems. Your agent creation might be dynamic—loading from configuration, database, or user choice. Factory decouples "which agent type" (decided at runtime) from "how to create it" (stateless factory code). This is professional architecture.


Part 3: Observer Pattern — Event-Driven Architecture

The Problem: Tight Coupling Between Components

Imagine agents need to react to events:

Loading Python environment...

The Observer pattern decouples senders from receivers using an event bus.

The Solution: Observer Implementation

Loading Python environment...

How it works:

  1. Observer is a protocol (interface) - any object with update() can observe.
  2. EventBus maintains a list of observers and publishes events to all.
  3. Observers (Agent, TaskQueue, Logger) react independently when events are published.
  4. Adding new observer types requires no changes to EventBus.

💬 AI Colearning Prompt

"Explain how the Observer pattern differs from polling. In polling, an agent repeatedly checks 'Has an event happened?' In Observer, the event bus notifies agents. Why is event-driven better for AI agent systems that need to react in real-time?"

🚀 CoLearning Challenge

Ask your AI Co-Teacher:

"Extend this system with event filtering: observers should only receive events they care about. Implement a subscription system where agents subscribe to specific event types, and EventBus only notifies relevant observers."

Expected Outcome: You'll understand selective notification, reducing unnecessary processing.


Part 4: Strategy Pattern — Runtime Algorithm Selection

The Problem: Hardcoded Decision Logic

Agents need different decision-making strategies depending on context:

Loading Python environment...

The Strategy pattern encapsulates algorithms so they're interchangeable.

The Solution: Strategy Implementation

Loading Python environment...

How it works:

  1. DecisionStrategy defines the interface for all strategies.
  2. Concrete strategies (Aggressive, Defensive, Balanced, Adaptive) implement different algorithms.
  3. Agent holds a reference to a strategy and delegates decisions to it.
  4. set_strategy() switches strategies at runtime without changing Agent code.

🎓 Expert Insight

Strategy pattern is essential in AI systems. Different models, different reasoning approaches, different risk profiles—all are strategies. By encapsulating them, agents adapt their behavior without core logic changes. This is how real AI systems handle A/B testing and experimentation.

🚀 CoLearning Challenge

Ask your AI Co-Teacher:

"Design a CompoundStrategy that combines multiple strategies (like an ensemble). Have an agent use multiple strategies and aggregate their decisions. Show how this pattern enables collaborative decision-making."

Expected Outcome: You'll understand strategy composition, a technique used in real ensemble AI systems.


Part 5: Bringing It All Together — The Multi-Agent Architecture

Now you'll integrate all 4 patterns into a cohesive system:

Loading Python environment...

What you've accomplished:

  1. Singleton (AgentManager): Single coordination point for all agents
  2. Factory (AgentFactory): Dynamic agent creation by type
  3. Observer (EventBus): Event-driven agent communication
  4. Strategy: Each agent uses a decision strategy

These patterns work together seamlessly because each solves one specific problem:

  • Singleton handles global state
  • Factory handles object creation
  • Observer handles loose coupling communication
  • Strategy handles algorithm selection

🎓 Expert Insight

This integrated system represents professional architecture. In production AI systems:

  • Singleton coordinates resources (expensive to create, need single instance)
  • Factory enables dynamic agent creation from config or user input
  • Observer enables asynchronous, loosely-coupled agent communication
  • Strategy enables experimentation with different reasoning approaches

Learning to combine patterns is what separates architects from code writers.


Challenge: Building Complex AI Systems with Design Patterns

In this capstone challenge, you'll integrate all four design patterns (plus additional ones) into a complete agent orchestration system. This is where theory meets practice—designing production-ready architectures.


Part 1: Plan Multi-Pattern System with AI

Your Role: System architect planning integration of 4 design patterns with AI collaboration

Planning Exercise: Design Multi-Pattern Agent Architecture

You're building a customer service platform that needs all 4 design patterns working together. Instead of manually typing 200+ lines of pattern code, you'll PLAN the architecture with AI, then have AI generate it.

💬 AI CoLearning Prompt - Understanding Pattern Integration Needs

"I'm building a customer service agent system with these requirements:

Requirement 1: Single Manager

  • Only ONE AgentManager should exist globally (not multiple instances)
  • All parts of the system access the SAME manager instance

Requirement 2: Dynamic Agent Creation

  • Create ChatAgent, TicketAgent, EscalationAgent by type name
  • Add new agent types without modifying creation code

Requirement 3: Event-Driven Communication

  • Agents notify each other via events (not direct calls)
  • Adding new agents doesn't require modifying event system

Requirement 4: Swappable Routing Logic

  • Route messages using different strategies (sentiment-based, round-robin)
  • Switch strategies at runtime without code changes

For EACH requirement, tell me:

  1. Which design pattern solves this problem?
  2. What does that pattern do?
  3. How does it solve the problem?
  4. Give me a simple plain-language architecture description (no code yet!)"

Expected Understanding: AI will map:

  • Requirement 1 → Singleton pattern (ensures single instance)
  • Requirement 2 → Factory pattern (decouples creation from types)
  • Requirement 3 → Observer pattern (event-driven, loose coupling)
  • Requirement 4 → Strategy pattern (encapsulates algorithms)

You'll understand WHAT each pattern does BEFORE seeing implementation code.

💬 AI CoLearning Prompt - Planning Pattern Interactions

"Now that I know the 4 patterns, help me plan how they work TOGETHER:

My Architecture Plan:

  • AgentManager (Singleton) coordinates everything
  • AgentFactory (Factory) creates agents
  • EventBus (Observer) handles communication
  • RoutingStrategy (Strategy) decides which agent processes messages

Help me think through the interactions:

  1. When a message arrives, what's the flow? (Manager → Strategy → Agent → EventBus?)
  2. How does the Manager use the Factory? (Does it call Factory.create()?)
  3. How do agents register with EventBus? (Manager does it, or agents do it themselves?)
  4. Can I swap the RoutingStrategy after the system starts?
  5. What's the initialization order? (Create patterns in what sequence?)

Give me a step-by-step flow diagram in plain language showing how a message travels through all 4 patterns."

Expected Understanding: AI will explain the interaction flow:

  1. Manager receives message
  2. Manager asks RoutingStrategy which agent to use
  3. Manager uses Factory to create agent if needed (or retrieves existing)
  4. Agent processes message
  5. Agent publishes result to EventBus
  6. Other agents subscribed to EventBus react to event

You'll understand the DEPENDENCIES between patterns before implementing.


Part 2: Generate System and Validate Design

Your Role: Design validator working with AI to generate and refine the multi-pattern system

AI-Assisted Implementation

Instead of typing 300+ lines of pattern code manually, you'll have AI generate the complete system based on your architecture plan from Part 1, then YOU validate it.

💬 AI CoLearning Prompt - Generate Complete Multi-Pattern System

"Based on my architecture plan (4 patterns working together), generate the complete Python code for my agent system:

Requirements:

  1. AgentManager (Singleton pattern):
    • __new__() ensures only one instance
    • _initialized flag prevents re-initialization
    • register_agent(), route_message() methods
    • Holds references to EventBus and RoutingStrategy
  2. AgentFactory (Factory pattern):
    • _registry dict mapping type names to classes
    • create(agent_type, name) creates agents dynamically
    • register(type_name, agent_class) adds new types
    • Supports ChatAgent, TicketAgent, EscalationAgent
  3. EventBus (Observer pattern):
    • _observers list of subscribers
    • attach(observer), detach(observer), notify(event) methods
    • Supports any object with update(event_type, data) method
  4. RoutingStrategy (Strategy pattern):
    • Abstract base with route(message) method
    • SentimentBasedStrategy (routes by keywords like 'urgent', 'ticket')
    • RoundRobinStrategy (cycles through agents)
  5. Agent base class:
    • Abstract with process(message) method
    • ChatAgent, TicketAgent, EscalationAgent concrete implementations

Important:

  • Add type hints to everything
  • Include docstrings explaining each pattern's role
  • Show main.py demonstrating all patterns working together
  • Use proper module structure (patterns/, agents/, main.py)

Generate the complete code. I'll validate it against my architecture plan."

Expected AI Output: ~150-200 lines of complete, working code implementing all 4 patterns with proper integration.


Validation Exercise: Check AI's Pattern Implementation

Your task: Read the AI-generated code and validate these architectural decisions:

✅ Validation Checklist:

  1. Singleton Pattern:

    • Does AgentManager have _instance class variable? ✓
    • Does __new__() return same instance every time? ✓
    • Does __init__() guard against re-initialization? ✓
    • Test: Create two references - are they the same object (same id)? ✓
  2. Factory Pattern:

    • Does AgentFactory have a registry dict? ✓
    • Can I create agents without importing concrete classes? ✓
    • Can I register new agent types without modifying factory code? ✓
    • Test: Add new agent type - does it work without editing Factory? ✓
  3. Observer Pattern:

    • Does EventBus maintain list of observers? ✓
    • Can observers attach/detach dynamically? ✓
    • Does notify() call update() on all observers? ✓
    • Test: Add 3 agents as observers, publish event - do all receive it? ✓
  4. Strategy Pattern:

    • Is RoutingStrategy an abstract base class? ✓
    • Can I create multiple concrete strategies? ✓
    • Can AgentManager's strategy be swapped at runtime? ✓
    • Test: Switch from SentimentBased to RoundRobin - does routing change? ✓
  5. Pattern Integration:

    • Does AgentManager use AgentFactory to create agents? ✓
    • Does AgentManager use RoutingStrategy to route messages? ✓
    • Do agents publish events to EventBus? ✓
    • Does the system work end-to-end (message in → routed → processed → event out)? ✓

🤝 CoLearning Convergence - Refining the Design

After validating the basic implementation, ask AI to enhance it:

"The basic 4-pattern system works! Now enhance it with these real-world features:

  1. Add logging to AgentManager showing which pattern is used for each operation
  2. Add error handling: what if Factory can't create agent type?
  3. Add metrics: track how many messages each strategy routes
  4. Add event filtering: agents subscribe only to specific event types

Show me the enhanced code focusing on production-readiness."

Expected Outcome: AI adds production features while maintaining the 4-pattern architecture. You'll see how patterns compose into robust systems.

Deliverable

Write 2-paragraph summary: "How I Validated and Enhanced a Multi-Pattern System" explaining:

  • What architecture decisions you validated
  • What production features you added
  • Why pattern composition enables extensibility

Part 3: Challenge AI with Complex Architecture Questions

Your Role: Student testing AI's understanding of pattern interactions

Challenge Design Scenarios

Ask AI to handle these cases:

Challenge 1: Pattern Conflicts

"If I use Singleton for AgentManager and Dependency Injection to pass the manager to agents, which is better? Can I use both? What problems could arise if I mix them?"

Expected learning: AI explains trade-offs between patterns and when to mix/match approaches.

Challenge 2: Pattern Composition

"I want to add three more patterns: Mediator (for agent communication), Command (for queuing tasks), Decorator (for dynamic capabilities). How do they interact with Singleton, Factory, Observer, and Strategy? Show the architecture diagram."

Expected learning: AI shows how multiple patterns compose into larger systems without conflicting.

Challenge 3: Testing and Patterns

"With Singleton and Observer, testing becomes harder (global state, hidden dependencies). How would you design these patterns to be testable? Should I use Dependency Injection instead?"

Expected learning: AI explains testability implications of patterns and how to design for both.

Deliverable

Document your three challenges, AI's responses, and your understanding of pattern trade-offs and composition.


Part 4: Build Complete Multi-Pattern Agent Orchestration System

Your Role: Architect designing production system

Create a professional multi-agent system integrating all four patterns:

agent_system/
├── patterns/
│ ├── __init__.py
│ ├── singleton.py # AgentManager (Singleton)
│ ├── factory.py # AgentFactory (Factory)
│ ├── observer.py # EventBus (Observer)
│ └── strategy.py # RoutingStrategy (Strategy)
├── agents/
│ ├── __init__.py
│ ├── base.py # Agent base class
│ ├── chat_agent.py # Concrete agent
│ ├── ticket_agent.py # Concrete agent
│ └── escalation_agent.py
├── events/
│ ├── __init__.py
│ └── events.py # Event definitions
└── main.py # Integration

patterns/singleton.py:

Loading Python environment...

patterns/factory.py:

Loading Python environment...

patterns/observer.py:

Loading Python environment...

patterns/strategy.py:

Loading Python environment...

agents/base.py:

Loading Python environment...

agents/chat_agent.py:

Loading Python environment...

main.py:

Loading Python environment...

Your task: Expand this system with:

  1. Add TicketAgent and EscalationAgent
  2. Implement EventBus with agent event handlers
  3. Add Mediator pattern for complex agent communication
  4. Create comprehensive test suite for all patterns
  5. Write architecture guide: design_patterns_integration.md

Validation Checklist

  • ✅ AgentManager is true Singleton (same instance everywhere)
  • ✅ AgentFactory creates agents without revealing classes
  • ✅ EventBus allows pub-sub between agents
  • ✅ RoutingStrategy can be swapped at runtime
  • ✅ All patterns work together seamlessly
  • ✅ Adding new agent type requires only Factory registration
  • ✅ Adding new routing strategy needs only new Strategy class

Deliverable

Complete multi-agent system with:

  • All 4 core patterns (Singleton, Factory, Observer, Strategy)
  • At least 3 concrete agent types
  • Multiple routing strategies
  • Event system connecting agents
  • Comprehensive test suite
  • Architecture documentation

Part 5: Reflect on All Chapter 30 Concepts

Your Role: Educational synthesist integrating all learning

This is unique to the capstone—you'll reflect on what you've learned across all five lessons.

Reflection Prompt

Write a comprehensive reflection document: chapter_25_integration_reflection.md with sections:

Section 1: Inheritance and MRO (Lesson 1)

Reflect on:

  • How did understanding Method Resolution Order change your thinking about class hierarchies?
  • When would you use single vs multiple inheritance?
  • How did inheritance patterns appear in later lessons?

Section 2: Polymorphism and Duck Typing (Lesson 2)

Reflect on:

  • What's the key insight that separates polymorphism from duck typing?
  • In your multi-agent system, where did you use each approach? Why?
  • How would your design differ if you HAD to use duck typing everywhere?

Section 3: Composition Over Inheritance (Lesson 3)

Reflect on:

  • Your agents are composed from engines. How is this better than inheritance?
  • What would the codebase look like if agents inherited from TicketAgent, ChatAgent, etc.?
  • How did composition principles appear in your strategy and observer implementations?

Section 4: Special Methods and Protocols (Lesson 4)

Reflect on:

  • How did special methods make your custom types feel like built-ins?
  • In an agent system, where might you use call, enter/exit, or iter?
  • What's the relationship between protocols and polymorphism?

Section 5: Design Patterns Integration (Lesson 5)

Reflect on:

  • How do Singleton, Factory, Observer, and Strategy solve fundamental OOP problems?
  • Could you design your system with only some patterns? What would you lose?
  • What's the relationship between design patterns and the OOP concepts from Lessons 1-4?

Section 6: Architectural Synthesis

Reflect on:

  • In your system, inheritance is used for agent types. Composition is used for agent capabilities. Polymorphism makes routing work. Special methods make events feel natural.
  • How are all these concepts working together?
  • Can you trace a message through your system and identify which OOP concept is responsible at each step?
  • What would break if you removed each concept?

Deliverable

Complete chapter_25_integration_reflection.md with thoughtful answers to all reflection questions, demonstrating deep understanding of how all Chapter 30 concepts interconnect.


Try With AI

How do you coordinate Singleton (AgentManager), Factory (agent creation), Observer (events), and Strategy (routing) in one system?

🔍 Explore Pattern Integration:

"Show me how AgentManager (Singleton) uses AgentFactory (Factory) to create agents, EventBus (Observer) to broadcast events, and RoutingStrategy (Strategy) to route messages. Trace a message through all 4 patterns."

🎯 Practice Pattern Composition:

"Design a system where Factory creates agents, Singleton manages them, Observer notifies on state changes, and Strategy determines behavior. Explain dependency flow and initialization order."

🧪 Test Pattern Interactions:

"What happens when AgentFactory creates an agent that registers with EventBus and AgentManager simultaneously? Show the sequence of method calls and explain potential race conditions."

🚀 Apply to Production Architecture:

"Build a complete multi-agent system using all Chapter 30 concepts: inheritance (agent types), polymorphism (dispatch), composition (capabilities), special methods (Event eq), and all 4 patterns. Explain design decisions."