News Ticker

Enum Strategy Pattern with Lambdas

In this post I would like to show how the strategy pattern can be implemented as an enum with lambdas.

Learn more about design patterns

Programming Foundations: Design Patterns
Java Design Patterns: Creational
Java EE: Design Patterns and Architecture
Spring: Design Patterns

The Strategy Pattern is one of the Gang of Four design patterns published in thier book: Elements of Reusable Object book. The intent of the strategy pattern is:

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

We will develop a simple calculator where the strategies are basic arithmetic operations.

We start with an interface that defines a single abstract method.

@FunctionalInterface
public interface OperationStrategy {
   T compute(T x, T y);
}

We now implement each arithmetic operation using a lambda expression.

public enum Operation implements OperationStrategy {
  ADD((x, y) -> x + y),
  SUBTRACT((x, y) -> x - y),
  MULTIPLY((x, y) -> x * y),
  DIVIDE((x, y) -> x / y),
  MAX(Double::max);

  private OperationStrategy operationStrategy;
  
  Operation(final OperationStrategy operationStrategy) {
    this.operationStrategy = operationStrategy;
  }

  @Override
  public Double compute(Double x, Double y) {
    return operationStrategy.compute(x, y);
  }
}

A series of tests prove that it works.

@RunWith(MockitoJUnitRunner.class)
public class OperationStrategyTest {

  @Test
  public void shouldAddTwoNumbers() {
    assertThat(Operation.ADD.compute(5d, 5d))
      .isEqualTo(new Double(10));
  }

  @Test
  public void shouldSubtractTwoNumbers() {
    assertThat(Operation.SUBTRACT.compute(10d, 5d))
      .isEqualTo(new Double(5d));
  }

  @Test
  public void shouldMultiplyTwoNumbers() {
    assertThat(Operation.MULTIPLY.compute(5d, 5d))
      .isEqualTo(new Double(25));
  }

  @Test
  public void shouldDivideTwoNumbers() {
    assertThat(Operation.DIVIDE.compute(10d, 2d))
      .isEqualTo(new Double(5d));
  }

  @Test
  public void shouldDetermineMaximumOfTwoNumbers() {
    assertThat(Operation.MAX.compute(10d, 5d))
      .isEqualTo(new Double(10d));
  }
public enum Operation implements OperationStrategy {

ADD((x, y) -> x + y),
SUBTRACT((x, y) -> x - y),
MULTIPLY((x, y) -> x * y),
DIVIDE((x, y) -> x / y),
MAX(Double::max);

private OperationStrategy operationStrategy;

Operation(final OperationStrategy operationStrategy) {
this.operationStrategy = operationStrategy;
}

@Override
public Double compute(Double x, Double y) {
return operationStrategy.compute(x, y);
}
}

The use of lambdas as strategies reduces boilerplate code quite substantially, though it would not be correct to lambdas if the strategy is complex and requires a lot of code. It would become cumbersome.

A git repository of this code is available here: https://github.com/atheedom/Java8

Other articles that you might find interesting:

Leave a Reply

%d bloggers like this: