Design Patterns
Design patterns are reusable solutions to recurring software design problems. The Gang of Four (GoF) catalog of 23 patterns remains the foundation of object-oriented design, organized into Creational, Structural, and Behavioral categories.
Contents 4 Sections
1Creational Patterns
Creational patterns deal with object creation, decoupling the client from the created object's class.
Singleton one instance globally
``typescript
class Database {
private static instance: Database;
private constructor() {}
static getInstance(): Database {
if (!Database.instance) Database.instance = new Database();
return Database.instance;
}
}
const db = Database.getInstance(); // always same instance
``
Factory Method subclass decides which object to create
``typescript
abstract class Notification {
abstract send(message: string): void;
static create(type: "email" | "sms" | "push"): Notification {
const map = { email: EmailNotification, sms: SMSNotification, push: PushNotification };
return new map[type]();
}
}
``
Builder fluent construction of complex objects
``typescript
const query = new QueryBuilder()
.select("id", "name", "email")
.from("users")
.where("active = true")
.orderBy("created_at", "DESC")
.limit(20)
.build();
``
Abstract Factory family of related objects without specifying concrete classes. Example: UI toolkit for different OS themes (Windows vs macOS).
Prototype clone existing objects. Useful when object creation is expensive.
2Structural Patterns
Structural patterns deal with composing objects into larger structures.
Adapter convert one interface to another ```typescript // Legacy interface class OldLogger { log(msg: string) { console.log(msg); } }
// New interface expected interface ILogger { info(msg: string): void; error(msg: string): void; }
class LoggerAdapter implements ILogger { constructor(private old: OldLogger) {} info(msg: string) { this.old.log("[INFO] " + msg); } error(msg: string) { this.old.log("[ERROR] " + msg); } } ```
Decorator wrap objects to add behavior without subclassing ```typescript interface Coffee { cost(): number; description(): string; }
class MilkDecorator implements Coffee { constructor(private coffee: Coffee) {} cost() { return this.coffee.cost() + 0.5; } description() { return this.coffee.description() + ", milk"; } } // Stackable: new Sugar(new Milk(new BasicCoffee())) ```
Facade simplified interface to a complex subsystem
``typescript
class OrderFacade {
checkout(items, user) {
this.inventoryService.reserve(items);
this.paymentService.charge(user, total);
this.emailService.sendConfirmation(user);
this.warehouseService.pack(items);
}
}
``
Proxy control access to an object (lazy loading, caching, auth checks)
Composite treat individual and composite objects uniformly (file/folder tree)
3Behavioral Patterns
Behavioral patterns deal with communication between objects.
Observer publish/subscribe event system
``typescript
class EventEmitter {
private listeners = new Map``
Strategy swap algorithms at runtime ```typescript interface SortStrategy { sort(data: number[]): number[]; } class BubbleSort implements SortStrategy { sort(d) { /* ... */ return d; } } class QuickSort implements SortStrategy { sort(d) { /* ... */ return d; } }
class Sorter { constructor(private strategy: SortStrategy) {} setStrategy(s: SortStrategy) { this.strategy = s; } sort(data: number[]) { return this.strategy.sort(data); } } ```
Command encapsulate requests as objects (supports undo/redo) ```typescript interface Command { execute(): void; undo(): void; }
class History { private stack: Command[] = []; execute(cmd: Command) { cmd.execute(); this.stack.push(cmd); } undo() { this.stack.pop()?.undo(); } } ```
Chain of Responsibility pass request along handler chain (Express middleware)
Template Method define algorithm skeleton, let subclasses fill in steps
4Modern Patterns & Principles
Repository Pattern abstract data access layer
```typescript
interface UserRepository {
findById(id: string): Promise
// Implementations: PostgresUserRepository, MongoUserRepository, InMemoryUserRepository (tests) ```
CQRS (Command Query Responsibility Segregation)
Separate read (query) and write (command) models.
``
Command side: CreateOrderCommand → validates → emits OrderCreated event
Query side: GetOrdersQuery → optimized read model → returns DTOs
``
Event Sourcing store state changes as events, rebuild state by replaying.
Dependency Injection pass dependencies in rather than creating them internally. ```typescript // Bad: hard-coded dependency class OrderService { db = new PostgresDB(); }
// Good: injected dependency class OrderService { constructor(private readonly db: IDatabase) {} } ```
- Anti-Patterns to Avoid
- God Object: one class does everything
- Spaghetti Code: tangled, unstructured control flow
- Golden Hammer: applying one pattern everywhere
- Premature Optimization: optimize before profiling
Explore the Full Portfolio
This is the complete portfolio of Sufi Khan Sulaiman, a technology leader specialising in B2B commerce and digital automation. Start from the Home page for the overview, then move through two decades of career experience across FLIR Systems, Lorex Technology, and 1c Platform, and the full catalogue of project case studies spanning headless commerce migrations, AI recommendation engines, and multi-channel fulfilment systems.
The skills and certifications page maps the technical and leadership capabilities behind the work, while the articles and the knowledge base break down the thinking into actionable frameworks. For hands-on learning, the tutorials and applications sections cover practical builds from front-end fundamentals to full-stack web apps.
For consulting engagement, the expertise page outlines service offerings, the ecommerce hub covers platform architecture and automation strategy, and the ecommerce guide (PDF) is a downloadable 55-page field manual. When you are ready to talk, the contact page is the direct line.