In this lesson, you will learn how to use the Strategy Pattern to dynamically swap business logic based on runtime request data.
The Problem: Conditional Bloat
As your application grows, you often need to handle the same type of request differently depending on who is sending it or what the payload contains. A common mistake is to write large if/else or switch blocks inside your controller:
// Don't do this!
if (user.type === 'premium') {
// process premium logic
} else if (user.type === 'guest') {
// process guest logic
}
This makes your controllers brittle and hard to test. The Strategy Pattern solves this by encapsulating each algorithm (the "strategy") into its own independent object that follows a common interface.
Implementing the Strategy Pattern
Instead of hardcoding the logic, you create a "strategy map" that selects the correct handler at runtime.
1. Define your strategies
const strategies = {
premium: {
handle: (req) => { /* logic for premium users */ }
},
guest: {
handle: (req) => { /* logic for guest users */ }
}
};
2. Dynamically select at runtime
By using the request context, you can pick the strategy without writing complex conditionals.
function requestHandler(req, res) {
const userType = req.headers['x-user-type'];
const strategy = strategies[userType] || strategies.guest;
return strategy.handle(req);
}
Why this matters
By decoupling the selection logic from the execution logic, your code becomes modular. If you need to add a new trial user type, you simply add a new key to your strategies object without ever modifying the requestHandler function itself. This follows the Open/Closed Principle: your code is open for extension but closed for modification.
This approach pairs perfectly with your existing Service Layer Abstraction, allowing you to keep your controllers clean while delegating the specific "how" of request processing to specialized strategy modules.
Key Takeaway: The Strategy Pattern replaces complex conditional chains with a lookup map, allowing your application to scale its logic by plugging in new handlers without modifying existing code.