HT
How Things Work
System Online

Strategy, Factory & Observer

The Gang of Four patterns you actually reach for daily — swapping algorithms, abstracting creation, and broadcasting change, all built on programming to an interface.

How It Works

Design patterns are named, reusable solutions to recurring design problems. Three of the most useful in everyday code are Strategy (interchangeable algorithms), Factory (abstracted object creation), and Observer (one-to-many change notification). They all share one foundation — depend on interfaces, not implementations — which is what makes code extensible and loosely coupled.

1
Strategy — Interchangeable Algorithms

Define a family of algorithms behind a common interface and make them swappable at runtime. The context holds a reference to a strategy and delegates to it, never knowing which concrete one it has. Adding a new algorithm is a new class — no edits to the context. It's the object-oriented replacement for a behavioral switch statement.

2
Factory — Centralized Creation

A factory encapsulates the decision of which concrete class to instantiate. Callers ask for what they want (by type or parameters) and receive an object that satisfies an interface, without coupling themselves to concrete constructors. This isolates creation logic and makes it easy to add or vary the products.

3
Observer — Publish/Subscribe

A subject maintains a list of observers and notifies them whenever its state changes. Observers subscribe and unsubscribe dynamically and react independently. It models one-to-many dependencies with loose coupling — the subject doesn't know what its observers do, only that they implement update().

4
The Common Thread

All three (and most GoF patterns) rest on the same principle: program to an interface, not an implementation. By depending on abstractions, you let concrete types vary without changing the code that uses them — the practical embodiment of polymorphism and the Open/Closed principle.

Key Concepts

♟ïļStrategy

Encapsulate interchangeable algorithms behind an interface and select one at runtime. Replaces behavioral switches.

🏭Factory

Centralize and abstract object creation so callers depend on an interface, not concrete constructors.

ðŸ“ĄObserver

A subject notifies a dynamic list of subscribers on state change — one-to-many, loosely coupled.

🔌Program to an Interface

Depend on abstractions so implementations can vary without touching client code. The core GoF principle.

🗂ïļBehavioral vs Creational

Strategy/Observer are behavioral (how objects interact); Factory is creational (how objects are made).

ðŸ§ąComposition over Inheritance

These patterns inject collaborators rather than subclass — favoring flexible composition.

Strategy, Factory & Observer
tsx
1// STRATEGY — swap an algorithm behind one interface.
2interface ShippingStrategy { cost(weight: number): number; }
3class Express implements ShippingStrategy { cost(w) { return 15 + w; } }
4class Drone implements ShippingStrategy { cost(w) { return 40 + w * 2; } }
5checkout.setStrategy(new Drone()); // chosen at runtime
6checkout.total(); // uses whatever strategy is set
7
8// FACTORY — centralize creation; callers don't 'new' concrete types.
9class ExporterFactory {
10 static create(kind: string): Exporter {
11 switch (kind) {
12 case "pdf": return new PdfExporter();
13 case "csv": return new CsvExporter();
14 default: throw new Error("unknown format");
15 }
16 }
17}
18
19// OBSERVER — one subject notifies many subscribers on change.
20class StockPrice {
21 private observers: Observer[] = [];
22 subscribe(o: Observer) { this.observers.push(o); }
23 set(price: number) { this.observers.forEach(o => o.update(price)); }
24}
ðŸ’Ą
Why This Matters

GoF patterns are a shared vocabulary among developers and a constant interview topic — saying 'use a strategy here' communicates a whole design instantly. More importantly, recognizing when a problem fits a known pattern (and when it doesn't) lets you write extensible code on purpose rather than rediscovering these solutions the hard way.

Common Pitfalls

⚠Pattern obsession — forcing patterns where a simple function or conditional would do (over-engineering).
⚠Turning every class into a factory/strategy 'just in case', adding indirection with no real variation.
⚠Observer memory leaks: subscribers that never unsubscribe keep the subject (and themselves) alive.
⚠Strategy classes that share so much state they should have been one parameterized method.
⚠Confusing the patterns' intent — e.g. using a Factory when you really need Dependency Injection.
Real-World Use Cases

1The Pricing Engine Full of If-Else

Scenario

A checkout calculates discounts with a sprawling if/else over customer tier, promo code, season, and region. Every new promotion edits this method, and bugs in one branch break unrelated pricing.

Problem

All pricing variations live in one growing conditional — a maintenance nightmare and an Open/Closed violation. Testing one rule means navigating the whole tangle.

Solution

Apply Strategy: each pricing rule becomes a DiscountStrategy implementing calculate(cart). The engine composes the applicable strategies at runtime. New promotions are new classes, independently testable, with no edits to existing rules.

ðŸ’Ą

Takeaway: When behavior varies along an axis and keeps growing, Strategy turns a fragile conditional into a set of small, swappable, testable classes — and makes the engine closed for modification.

2Reacting to an Event Without Coupling

Scenario

When an order is placed, the system must update inventory, send a confirmation email, notify analytics, and award loyalty points. Cramming all of that into placeOrder() couples it to four subsystems.

Problem

Direct calls make the order code depend on every subsystem, so it can't change or be tested in isolation, and adding a fifth reaction means editing core order logic again.

Solution

Use Observer (in-process pub/sub / domain events): placeOrder() publishes an OrderPlaced event; inventory, email, analytics, and loyalty each subscribe and react independently. The order code knows nothing about them, and new reactions just subscribe.

ðŸ’Ą

Takeaway: Observer decouples 'something happened' from 'who cares'. The subject broadcasts; subscribers react on their own — letting you add or remove reactions without touching the source of the event.

Join the discussion

Comments

?

Loading comments...

Cookie preferences

We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.