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