Strategy Design Pattern Using Java Enum

In this post, we’ll explore the implementation of the Strategy Design Pattern using Java Enum.

· Prerequisites
· Overview
∘ What is the Strategy Pattern?
∘ How is it implemented?
· Step-by-Step Implementation
∘ Traditional implementation of the Strategy design pattern
∘ Enum implementation of the Strategy design pattern
· Pros and Cons of Using Enums for Strategy Pattern Implementation
· Conclusion
· References

Prerequisites

This is the list of all the prerequisites:

  • Maven
  • Java 21
  • IntelliJ IDEA, Visual Studio Code, or another IDE

Overview

What is the Strategy Pattern?

The strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives runtime instructions as to which in a family of algorithms to use.

https://en.wikipedia.org/wiki/Strategy_pattern

How is it implemented?

  1. In the context class, identify an algorithm that’s prone to frequent changes. It may also be a massive conditional that selects and executes a variant of the same algorithm at runtime.
  2. Declare the strategy interface common to all variants of the algorithm.
  3. One by one, all algorithms are extracted into their classes. They should all implement the strategy interface.
  4. In the context class, add a field to store a reference to a strategy object. Provide a setter for replacing values of that field. The context should work with the strategy object only via the strategy interface. The context may define an interface that lets the strategy access its data.
  5. Clients of the context must associate it with a suitable strategy that matches the way they expect the context to perform its primary job.

Step-by-Step Implementation

Imagine you’re building an e-commerce platform where users can pay using various payment methods. After selecting a product to purchase, a user picks a payment method:

  • Credit Card
  • PayPal
  • Bitcoin

Traditional implementation of the Strategy design pattern

  • Strategy Interface
public interface PaymentStrategy {
void pay(double amount);
}
  • Strategy Classes
public class CreditCardPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using Credit Card.\n", amount);
}
}

public class PayPalPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using PayPal.\n", amount);
}
}

public class BitcoinPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using Bitcoin.\n", amount);
}
}
  • Context Class

The context class selects the strategy and executes the pay method of the selected strategy.

public class PaymentContext {
private PaymentStrategy strategy;

public void setStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}

public void checkout(double amount) {
if (strategy == null) {
throw new IllegalStateException("Payment strategy not set.");
}
strategy.pay(amount);
}
}
  • Client of the context
public class StrategyPatternDemo {
public static void main(String[] args) {
PaymentContext context = new PaymentContext();

context.setStrategy(new CreditCardPayment());
context.checkout(100);

context.setStrategy(new PayPalPayment());
context.checkout(250);

context.setStrategy(new BitcoinPayment());
context.checkout(500);
}
}
Paid $100.00 using Credit Card.
Paid $250.00 using PayPal.
Paid $500.00 using Bitcoin.

Process finished with exit code 0

Enum implementation of the Strategy design pattern

Now, let’s implement an example of a strategy pattern using enum. This implementation only requires an enum class and a client of the context.

public enum PaymentStrategy {

CREDIT_CARD {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using Credit Card.\n", amount);
}
},
PAYPAL {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using PayPal.\n", amount);
}
},
BITCOIN {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using Bitcoin.\n", amount);
}
};

public abstract void pay(double amount);
}

Each enum constant will override a method that implements a different strategy.

public class StrategyPatternDemo {
public static void main(String[] args) {
PaymentStrategy.CREDIT_CARD.pay(100);
PaymentStrategy.PAYPAL.pay(250);
PaymentStrategy.BITCOIN.pay(500);
}
}
Paid $100.00 using Credit Card.
Paid $250.00 using PayPal.
Paid $500.00 using Bitcoin.

Process finished with exit code 0

Another alternative: Enum with string mapping

public enum PaymentMappingStrategy {
CREDIT_CARD("cc") {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using Credit Card.\n", amount);
}
},
PAYPAL("paypal") {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using PayPal.\n", amount);
}
},
BITCOIN("btc") {
@Override
public void pay(double amount) {
System.out.printf("Paid $%.2f using Bitcoin.\n", amount);
}
};

private final String code;

PaymentMappingStrategy(String code) {
this.code = code;
}

public abstract void pay(double amount);

public static PaymentMappingStrategy fromCode(String code) {
return Arrays.stream(values()).filter(value -> value.code.equalsIgnoreCase(code))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unknown payment code: " + code));
}
}

Pros and Cons of Using Enums for Strategy Pattern Implementation

While the Enum Strategy Pattern is clean and elegant in many cases, it does have some limitations and disadvantages.

Here’s a concise table summarizing the pros and cons of using enums for the Strategy Pattern

Conclusion

Well done !!. In this post, we’ve explored the implementation of a strategy pattern using Enum Java.

The complete source code is available on GitHub.

Support me through GitHub Sponsors.

Thank you for reading!! See you in the next post.

References

👉 Link to Medium blog

Related Posts