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 comment