In the world of software design, flexibility and maintainability are crucial. One of the best ways to achieve this is through the Strategy Pattern—a behavioral design pattern that allows us to define a family of algorithms, encapsulate each one, and make them interchangeable.
Let’s break it down using a car example! 🚘
What is the Strategy Pattern?
The Strategy Pattern enables an object’s behavior to be selected at runtime. Instead of hardcoding logic inside an object, we delegate it to separate strategy classes that encapsulate different behaviors. This promotes the Open-Closed Principle—where code is open for extension but closed for modification.
Real-World Example: Cars and Their Behaviors 🚗⚡️⛽
Consider a car that can have different transmission types (manual, automatic, semi-automatic) and fuel types (gasoline, diesel, electric). Instead of tightly coupling the car’s logic to these behaviors, we use the Strategy Pattern to define separate classes for each.
🔹 Implementing Transmission Strategies
Each transmission type is an independent class that implements the TransmissionStrategy
interface:
export interface TransmissionStrategy {
changeGear(): void;
}
export class ManualTransmission implements TransmissionStrategy {
changeGear(): void {
console.log("Changing gear manually.");
}
}
export class AutomaticTransmission implements TransmissionStrategy {
changeGear(): void {
console.log("Changing gear automatically.");
}
}
export class SemiAutomaticTransmission implements TransmissionStrategy {
changeGear(): void {
console.log("Changing gear semi-automatically.");
}
}
🔹 Implementing Fuel Strategies
Similarly, different fuel types adhere to a FuelStrategy
interface:
export interface FuelStrategy {
refuel(): void;
}
export class Gasoline implements FuelStrategy {
refuel(): void {
console.log("Refueling gasoline...");
}
}
export class Diesel implements FuelStrategy {
refuel(): void {
console.log("Refueling diesel...");
}
}
export class Electric implements FuelStrategy {
refuel(): void {
console.log("Charging the battery...");
}
}
🔹 The Car Class Using Strategies
The Car
class now delegates behavior to the appropriate strategy:
export class Car {
private transmission: TransmissionStrategy;
private fuel: FuelStrategy;
constructor(transmission: TransmissionStrategy, fuel: FuelStrategy) {
this.transmission = transmission;
this.fuel = fuel;
}
setTransmission(transmission: TransmissionStrategy): void {
this.transmission = transmission;
}
setFuel(fuel: FuelStrategy): void {
this.fuel = fuel;
}
refuel(): void {
this.fuel.refuel();
}
changeGear(): void {
this.transmission.changeGear();
}
}
Why Use the Strategy Pattern? 🤔
✅ Flexibility: We can change the car’s transmission and fuel type dynamically at runtime.
✅ Encapsulation: Each behavior is encapsulated separately, making it easy to add new strategies.
✅ Maintainability: Avoids complex if-else conditions, making the code clean and modular.
✅ Reusability: Strategies can be reused across different contexts without modifications.
Example Usage 🚀
Now, let’s create different cars and modify their behaviors at runtime:
const manualCar = new Car(new ManualTransmission(), new Gasoline());
manualCar.changeGear(); // Output: Changing gear manually.
const automaticCar = new Car(new AutomaticTransmission(), new Electric());
automaticCar.changeGear(); // Output: Changing gear automatically.
const semiAutomaticCar = new Car(new SemiAutomaticTransmission(), new Diesel());
semiAutomaticCar.changeGear(); // Output: Changing gear semi-automatically.
manualCar.setTransmission(new AutomaticTransmission()); // Switching to automatic
semiAutomaticCar.setFuel(new Electric()); // Switching to electric
manualCar.changeGear(); // Output: Changing gear automatically.
semiAutomaticCar.refuel(); // Output: Charging the battery...
Final Thoughts 💡
The Strategy Pattern is a powerful tool for designing flexible and reusable software. By decoupling behaviors into independent strategies, we make our applications more adaptable to change.
If you found this insightful, drop a like and share this with your network! 🚀💬
Top comments (0)