Behavioral Design Patterns

Author: Htunn Thu Thu

Date: January 4, 2026

Tags: #SoftwareDesign #TypeScript #DesignPatterns #Behavioral

Introduction

Behavioral patterns focus on communication between objects and how responsibilities are distributed. Building my IoT monitoring platform taught me that how objects interact is just as important as how they're structured.

This guide covers four behavioral patterns I use constantly:

  • Observer Pattern - Objects reacting to state changes

  • Strategy Pattern - Swappable algorithms

  • Command Pattern - Encapsulating requests as objects

  • State Pattern - Object behavior based on internal state


Observer Pattern

Defines a one-to-many dependency so when one object changes state, all dependents are notified.

The Problem I Had

In my IoT platform, I needed multiple components to react when sensor data arrived:

My Solution: Observer Pattern

I implemented a publish-subscribe system:

Event Emitter Pattern (Node.js Style)

For my MCP server, I used Node.js EventEmitter:


Strategy Pattern

Defines a family of algorithms, encapsulates each one, and makes them interchangeable.

The Problem I Had

My Agentic LLM project needed different search strategies:

My Solution: Strategy Pattern

I extracted strategies into separate classes:

Real Example: LLM Provider Selection

Here's how I use Strategy for LLM provider selection in my agent:


Command Pattern

Encapsulates a request as an object, allowing parameterization and queuing of requests.

The Problem I Had

My MCP server needed to support undo/redo and command history:

My Solution: Command Pattern

I encapsulated operations as command objects:

Macro Commands (Composite)

For complex workflows, I create composite commands:


State Pattern

Allows an object to alter its behavior when its internal state changes.

The Problem I Had

In my IoT platform, sensor connections had complex state management:

My Solution: State Pattern

I encapsulated each state as a separate class:

Real Example: Scan State Machine

Here's my actual scan state machine from the MCP server:


Combining Behavioral Patterns

Here's how I combine multiple behavioral patterns in my IoT platform:


When to Use Each Pattern

Observer Pattern

βœ… Use when:

  • Multiple objects need to react to state changes

  • Loose coupling between subject and observers

  • Implementing event systems

❌ Avoid when:

  • Only one object cares about changes

  • Direct method calls are simpler

Strategy Pattern

βœ… Use when:

  • Multiple algorithms for the same task

  • Need to switch algorithms at runtime

  • Want to avoid conditional logic

❌ Avoid when:

  • Only one algorithm exists

  • Algorithm never changes

Command Pattern

βœ… Use when:

  • Need undo/redo functionality

  • Want to queue or log operations

  • Implementing macro commands

❌ Avoid when:

  • Simple method calls suffice

  • Don't need operation history

State Pattern

βœ… Use when:

  • Object behavior changes based on state

  • Complex state transitions

  • Many state-dependent conditionals

❌ Avoid when:

  • Few simple states

  • State logic is trivial


Conclusion

Behavioral patterns manage object interactions elegantly:

  • Observer: One-to-many notifications

  • Strategy: Interchangeable algorithms

  • Command: Encapsulated operations

  • State: State-based behavior

I use these patterns daily in my TypeScript projects for event-driven architectures, flexible algorithms, and complex state management.

What's Next?

References


Previous: ← Structural Patterns | Next: Component Design β†’

Last updated