Design Patterns – Are First-Class Functions a Substitute for the Strategy Pattern?

design-patternsfunctionsobject-oriented

The Strategy design pattern is often regarded as a substitute for first-class functions in languages that lack them.

So for example say you wanted to pass functionality into an object. In Java you'd have to pass in the object another object which encapsulates the desired behavior. In a language such as Ruby, you'd just pass the functionality itself in the form of an anonymous function.

However I was thinking about it and decided that maybe Strategy offers more than a plain anonymous function does.

This is because an object can hold state that exists independently of the period when it's method runs. However an anonymous function by itself can only hold state that ceases to exist the moment the function finishes execution.

In an object-oriented language that supports first-class functions, does the strategy pattern have any advantage over using functions?

Best Answer

When the language supports references to function (Java does since version 8), these are often a good alternative for strategies, because they usually express the same thing with less syntax. However, there are some cases where a real object can be useful.

A Strategy interface can have multiple methods. Let's take an interface RouteFindingStragegy as example, which encapsulates different route finding algorithms. It could declare methods like

  • Route findShortestRoute(Node start, Node destination)
  • boolean doesRouteExist(Node start, Node destination)
  • Route[] findAllPossibleRoutes(Node start, Node destination)
  • Route findShortestRouteToClosestDestination(Node start, Node[] destinations)
  • Route findTravelingSalesmanRoute(Node[] stations)

which then would all be implemented by the strategy. Some route-finding algorithms might allow internal optimizations for some of these use-cases and some might not, so the implementor can decide how to implement each of these methods.

Another case is when the strategy has an inner state. Sure, in some languages closures can have inner state, but when this inner state gets very complex, it often becomes more elegant to promote the closure to a full-fledged class.

Related Topic