Posted by: iainduncani | April 25, 2010

Closures in Java 7 and the Stategy Pattern

Java 7 is now set to include Closures allowing you to define function blocks of code to be executed at a later point in the code. I think that this will be a great addition to the language and make implementing the Strategy Pattern a much more pleasant experience. In order to show how the strategy pattern works and why adding Closures will make implementing it simpler consider the following class that calculates an employees pay rise, if the company has made better profit than last year they get a big pay rise, if it is the same a small pay rise and if the profits have gone down they get no pay rise:

public class PayRiseCalculator {

  private final int thisYearsProfit;

  private final int lastYearsProfit;

  public PayRiseCalculator(int _thisYearsProfit, int _lastYearsProfit) {
    super();
    this.thisYearsProfit = _thisYearsProfit;
    this.lastYearsProfit = _lastYearsProfit;
  }

  public double calculatePayRise(Employee _employee) {
    final double payRise_;

    if (thisYearsProfit > lastYearsProfit) {
      payRise_ = _employee.getSalary() * 0.05;
    } else if (thisYearsProfit > lastYearsProfit) {
      payRise_ = _employee.getSalary() * 0.01;
    } else {
      payRise_ = 0;
    }

    return payRise_;
  }

}

Re-Implement Using the Strategy Pattern

This class can be simplified a lot by using the Strategy Pattern by replacing the algorithm part of the method that calculates how much pay rise to give with a Strategy object:

public class PayRiseCalculator {

  private final PayRiseStrategy payRiseStrategy;

  public PayRiseCalculator(PayRiseStrategy _payRiseStrategy) {
    super();
    this.payRiseStrategy= _payRiseStrategy;
  }

  public double calculatePayRise(Employee _employee) {
    final double payRise_ = payRiseStrategy.calculate(_employee);

    return payRise_;
  }

}

This class has certainly now become simpler as well as being easier to extend with different strategies for calculating the pay rises of employees. However, where I think using this becomes cumbersome within Java is the extra classes that we have had to add in order to implement it. In order to make this change we will have to add a new interface and three new classes:

public interface PayRiseStrategy {

  public double calculate(Employee _employee);

}

public class ProfitIncreaseStrategy implements PayRiseStrategy {

  public double calculate(Employee _employee) {
    return _employee.getSalary() * 0.05;
  }

}

public class ProfitSteadyStrategy implements PayRiseStrategy {

  public double calculate(Employee _employee) {
    return _employee.getSalary() * 0.01;
  }

}

public class ProfitDecreaseStrategy implements PayRiseStrategy {

  public double calculate(Employee _employee) {
    return 0;
  }

}

The amount of code that is required to produce the same result has now ballooned and is split across multiple different classes making it harder to maintain and harder to see which part of the code is doing the important part because it is hidden behind so much boiler plate code. It is also quite dull to implement this pattern in Java because you spend more time writing the boiler plate and less time writing the fun algorithms.

Introducing Closures

Closures will help reduce some of these problems by allowing you to just write the method implementation (in this case for calculate) without having to have so much boiler plate code around it – no extra interfaces or classes will be required. In order to achieve this Java 7 is going to include a syntax for assigning a function to a variable such as this:

#double (Employee) payRiseStrategy;

This syntax means that the payRiseStrategy variable is a function that takes in a single argument of type Employee and returns a double. All functions defined in this way will have an invoke method that allows the function to be processed. This then allows us to re-write the PayRiseCalculator class like so:

public class PayRiseCalculator {

  private #double (Employee) payRiseStrategy;

  public PayRiseCalculator(#double (Employee) _payRiseStrategy) {
    super();
    this.payRiseStrategy= _payRiseStrategy;
  }

  public double calculatePayRise(Employee _employee) {
    final double payRise_ = payRiseStrategy.invoke(_employee);

    return payRise_;
  }

}

This is very similar to the implementation of the PayRiseCalculator using interfaces for the Strategy pattern.  The differences come when looking at how the strategy objects themselves are created and passed into this API. We will no longer need to have extra classes containing the algorithms, instead we can use a “lambda expression” (or function) to define them like so:

#double (Employee _employee) { _employee * 0.05 }

The syntax for declaring this function is very similar to the variable that we declared inside the PayRiseCalculator for storing it. The function declaration is stating that it will return a double and take an Employee as its argument that is assigned to the _employee variable. The function itself is then contained within the { } in a similar way to a method in Java. One of the peculiarities that you may have noticed is in the way the result is returned from the function. There is no return statement or semi-colon. The reasons behind this are explained by the proposal author’s blog. The explanation boils down to the fact that the return statement needs to differentiate itself from existing Java constructs, by not having a semi-colon this would not of been valid Java before so will be unique to this proposal without adding extra keywords. The return keyword could not be used as it could be ambiguous when used inside a function inside a method where it may not be obvious if the return is returning from the function or from the method where the function is declared.

As you can see from the discussion above closures will not allow you to do anything that you cannot already do in Java using interfaces and classes, they are essentially another way to write an anonymous inner class for an interface with a single method. The strategy pattern is a neat way of making code more extensible and re-usable but the ratio of boiler plate code to useful code is often too high in Java, especially when the algorithms that it is encapsulating are simple as was the case above. The addition of closures to Java reduce this ratio allowing developers to concentrate on writing the interesting bits of code which is why I think it will be a great addition to the language.

All of the syntax for Closures on this page is based on the current proposal for Java 7 available from here:


Leave a comment

Categories