Simplified Strategy Design Pattern: Deep Explanation with Java

Behavior Design Pattern To Define a Family of Algorithms

Mohammed Muwanga
4 min readMay 30, 2024

What is the Strategy Design Pattern?

The Strategy Design Pattern is a behavioral design pattern that allows you to define a family of algorithms, encapsulate each one, and make them interchangeable. This pattern lets the algorithm vary independently from the clients that use it.

In simpler terms, the Strategy pattern enables selecting an algorithm’s behavior at runtime. It is useful when you have multiple ways of doing something, and you want to choose which way to use dynamically.

For Example: an on-line Shopping Cart

Consider an online shopping cart where users can choose different payment methods (e.g., credit card, PayPal). The Strategy pattern allows dynamically changing the payment method without altering the code that processes the payment.

Key Components:

  1. Strategy Interface: Defines a common interface for all supported algorithms. [Payment Strategy]
  2. Concrete Strategies: Implement the strategy interface with specific algorithms. [Exact methods of payment, either Credit card or Paypal]
  3. Context: Maintains a reference to a Strategy object and uses it to execute the algorithm. [Runtime change of either available payment method]
  4. Client Execution

Structure:

UML Diagram

UML Diagram Illustrating Strategy Design Pattern
UML Illustration for Strategy Design Pattern

Code Sample: For Illustration

Strategy Interface

interface PaymentStrategy {
void pay(int amount);
}

Implementation for Concrete Strategies: A and B

class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String cardHolderName;

public CreditCardPayment(String cardNumber, String cardHolderName) {
this.cardNumber = cardNumber;
this.cardHolderName = cardHolderName;
}

@Override
public void pay(int amount) {
System.out.println(amount + " paid with credit card.");
}
}

class PayPalPayment implements PaymentStrategy {
private String email;
private String password;

public PayPalPayment(String email, String password) {
this.email = email;
this.password = password;
}

@Override
public void pay(int amount) {
System.out.println(amount + " paid using PayPal.");
}
}

Context:

class ShoppingCart {
private PaymentStrategy paymentStrategy;

public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}

public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}

Use the Strategy Pattern in a Client

public class StrategyPatternDemo {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();

// User chooses to pay with credit card
cart.setPaymentStrategy(new CreditCardPayment("1234567890123456", "John Doe"));
cart.checkout(100); // Output: 100 paid with credit card.

// User chooses to pay with PayPal
cart.setPaymentStrategy(new PayPalPayment("john.doe@example.com", "password123"));
cart.checkout(200); // Output: 200 paid using PayPal.
}
}

In the example provided, the shopping cart can switch between different payment methods seamlessly, demonstrating the power and versatility of the Strategy pattern in a real-world scenario.

Example Use Case 2: Choosing a Transportation Means

Consider a scenario where a user can choose different methods of transport to get from one location to another. The Strategy design pattern allows dynamically changing the travel method without altering the core travel logic.

Define the Strategy Interface

interface TravelStrategy {
void travel(String startLocation, String endLocation);
}

Implement Concrete Strategies

class CarTravel implements TravelStrategy {
@Override
public void travel(String startLocation, String endLocation) {
System.out.println("Traveling from " + startLocation + " to " + endLocation + " by car.");
}
}

class BicycleTravel implements TravelStrategy {
@Override
public void travel(String startLocation, String endLocation) {
System.out.println("Traveling from " + startLocation + " to " + endLocation + " by bicycle.");
}
}

class WalkingTravel implements TravelStrategy {
@Override
public void travel(String startLocation, String endLocation) {
System.out.println("Traveling from " + startLocation + " to " + endLocation + " by walking.");
}
}

Create the Context Class


class TravelContext {
private TravelStrategy travelStrategy;

public void setTravelStrategy(TravelStrategy travelStrategy) {
this.travelStrategy = travelStrategy;
}

public void executeTravel(String startLocation, String endLocation) {
travelStrategy.travel(startLocation, endLocation);
}
}

Use the Strategy Pattern in a Client

public class StrategyPatternDemo {
public static void main(String[] args) {
TravelContext travelContext = new TravelContext();

// User chooses to travel by car
travelContext.setTravelStrategy(new CarTravel());
travelContext.executeTravel("Home", "Office"); // Output: Traveling from Home to Office by car.

// User chooses to travel by bicycle
travelContext.setTravelStrategy(new BicycleTravel());
travelContext.executeTravel("Home", "Park"); // Output: Traveling from Home to Park by bicycle.

// User chooses to travel by walking
travelContext.setTravelStrategy(new WalkingTravel());
travelContext.executeTravel("Home", "Shop"); // Output: Traveling from Home to Shop by walking.
}
}

The Strategy design pattern allows you to define a family of algorithms or methods, encapsulate each one, and make them interchangeable. By using this pattern, you can easily change the behavior of an algorithm at runtime without modifying the clients that use it.

In this example, the travel application can switch between different transport methods (car, bicycle, walking) seamlessly, demonstrating the flexibility and power of the Strategy pattern in a real-world scenario.

Sign up to discover human stories that deepen your understanding of the world.

Mohammed Muwanga
Mohammed Muwanga

Written by Mohammed Muwanga

Web Design, Development, SEO and Ergonomics

No responses yet

Write a response

Recommended from Medium

Lists

See more recommendations