Behavior Parameterization in Java
The BP (Behavior Parameterization) is a software development technique which aims at facilitating to handle the frequent requirements changes.
BP with Lambda Functions
Lambda functions are around for several decades in languages like Lisp and, since its 8th release, the Java programming language includes them as well. They are a very practical way to provide BP in Java.
The idea is that, with lambda functions, it is possible to define standalone blocks of code, exactly in the same way as defining classes. These blocks of code are functions that don't belong to any given class, but are themself autonomous objects. Once defined, they can be used as input arguments to methods, or function's return types, or both. Doing so allows to write more generalized functions, having a more specific behavior, as their body isn't anymore statically defined,but it may be passed as a variable strategy, in the form of the input and output lamba functions parameters.
A simple example
Let's consider a simple example of a domain model consisting in two classes, Order
and Customer
, as follows:
Then, the following interface could be defined such that to expose this domain model via an API (Application Programming Interface):
As we can see, this interface allows to perform lots of operations on our domain model. Among others, implementing this interface allows to get collections of orders and customers sorted by different criteria, as well as individual orders or customers satisfying constraints like highest or lowest balance values.
But the most interesting are the last three methods:
The
getOrdersFilteredByFunction()
method takes two input parameters: a list of orders and a lambda function of the typeFunction<List<Order>, List<Order>>
. It returns another list of orders which is the result of filtering the input list, based on the criteria defined in the input lambda function. This way, instead of defining several filter methods, each one implementing its own sorting strategy, we can provide just one, which applies whatever strategy passed as one of the input parameters.The
getFilterFunctionForOrders()
method takes an orders collection as the input argument and returns a lambda expression. This lambda expression is of the typeFunction<List<Orders>, Customer>
and, when executed, it will return the first french customer found among the customers associated to the input orders collection.The
getCombinedFilter()
method goes even further and takes two lambda expressions as input arguments and returns another lambda expression which is the combination of the first two. Hence, given that the two input lambda expressions apply filters on the input orders colection, the third one returned as the result, when executed, return the orders collection resulting by applying these filters.
By using lambda expressions as input parameters and return types, we achieve our goal which consists in parameterizing the behaviour of our API. Hence, we don't have any more to provide, for example, all the possible filters in order to sort our orders and customers based on different criteria combinations, but we cover all the use cases with a single method, by providing the filter strategy as an input parameter or as a return type.
Here below is a code fragment from an unit test demonstrating how the BP is supposed to work:
In the unit test above, we start be defining two lambda expressions having the signature Function<List<Order>, List<Order>>
. Then, we call the OrderOperations.getCombinedFilter()
method by passing to it these two lambda expressions as input parameters. The return is another lambda expression of the same type which combines the first two. Here, we combine two filters, the first one looking for all the french customers and the second one looking for a particulat last name. Exection this lambda expression will return the list of french customers having this particular last name.
The full code may be found here. Enjoy !
Last updated