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:
__new__()controls instance creation. First call creates instance and saves it in_instance. Subsequent calls return the same instance.__init__()might be called multiple times (once per reference), so we guard initialization with_initializedflag.- 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:
Agentis an abstract interface. Concrete agents (ChatAgent, CodeAgent, DataAgent) implement it.AgentFactory.create_agent()takes a type string and returns the appropriate agent.- The registry pattern allows new agent types to be added without modifying the factory method.
- Code that uses agents doesn't care what concrete type it is—it just calls the
Agentinterface.
🚀 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
RAGAgentthat automatically registers itself without modifyingAgentFactorycode."
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:
Observeris a protocol (interface) - any object withupdate()can observe.EventBusmaintains a list of observers and publishes events to all.- Observers (
Agent,TaskQueue,Logger) react independently when events are published. - 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:
DecisionStrategydefines the interface for all strategies.- Concrete strategies (Aggressive, Defensive, Balanced, Adaptive) implement different algorithms.
Agentholds a reference to a strategy and delegates decisions to it.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:
- Singleton (
AgentManager): Single coordination point for all agents - Factory (
AgentFactory): Dynamic agent creation by type - Observer (
EventBus): Event-driven agent communication - 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:
- Which design pattern solves this problem?
- What does that pattern do?
- How does it solve the problem?
- 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:
- When a message arrives, what's the flow? (Manager → Strategy → Agent → EventBus?)
- How does the Manager use the Factory? (Does it call Factory.create()?)
- How do agents register with EventBus? (Manager does it, or agents do it themselves?)
- Can I swap the RoutingStrategy after the system starts?
- 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:
- Manager receives message
- Manager asks RoutingStrategy which agent to use
- Manager uses Factory to create agent if needed (or retrieves existing)
- Agent processes message
- Agent publishes result to EventBus
- 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:
- AgentManager (Singleton pattern):
__new__()ensures only one instance_initializedflag prevents re-initializationregister_agent(),route_message()methods- Holds references to EventBus and RoutingStrategy
- AgentFactory (Factory pattern):
_registrydict mapping type names to classescreate(agent_type, name)creates agents dynamicallyregister(type_name, agent_class)adds new types- Supports ChatAgent, TicketAgent, EscalationAgent
- EventBus (Observer pattern):
_observerslist of subscribersattach(observer),detach(observer),notify(event)methods- Supports any object with
update(event_type, data)method- RoutingStrategy (Strategy pattern):
- Abstract base with
route(message)method- SentimentBasedStrategy (routes by keywords like 'urgent', 'ticket')
- RoundRobinStrategy (cycles through agents)
- 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:
-
Singleton Pattern:
- Does AgentManager have
_instanceclass 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)? ✓
- Does AgentManager have
-
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? ✓
-
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? ✓
-
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? ✓
-
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:
- Add logging to AgentManager showing which pattern is used for each operation
- Add error handling: what if Factory can't create agent type?
- Add metrics: track how many messages each strategy routes
- 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:
- Add TicketAgent and EscalationAgent
- Implement EventBus with agent event handlers
- Add Mediator pattern for complex agent communication
- Create comprehensive test suite for all patterns
- 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."