Introduction
This is a widely used concept in software design. This article will have a look at the concept from different points of view in two major languages, C# and Java. This article will cover the command design pattern and generic delegates in C#, and it will guide you towards the alternatives in Java with some ways to overcome challenges you may face.
In C# you have delegates, which is pretty straightforward as far as sending a method as parameter in C#. This has not been the case with Java. Since Java does not have the concept of delegates we have to use interfaces to obtain a similar functionality in Java. Basically the command pattern explains this scenario in Java.
Delegates in C#
We define the delegate:
- public delegate int Operation(int i, int j);
We assign method to the delegate:
- Operation operation = (i, i1) => i + i1;
We can execute method like this:
- int result = operation(1, 2);
Command Pattern
Command pattern falls under behavioural patterns. Command can be sent from client to an invoker and once invoker invokes the command the receiver receives the notification.
Here's how we do a similar thing in Java:
-
- public interface Command {
- void execute();
- }
-
-
- public class EmployeeToStringCommand implements Command {
- private Employee employee;
- public EmployeeToStringCommand(Employee employee) {
- this.employee = employee;
- }
-
- @Override
- public void execute() {
- System.out.printf(employee.toString());
- }
- }
-
-
- public class CommandExecutor {
- public void invoke(Command command){
- command.execute();
- }
- }
-
-
- EmployeeToStringCommand employeeToStringCommand = new EmployeeToStringCommand(employee1);
- new CommandExecutor().invoke(employeeToStringCommand);
Command always wraps with the following information
- Method to invoke
- Owner of the method (Client instance created the command)
- And optionally any arguments required to complete execution of the command.
Note: As you are already aware, you can always use command pattern in C#, there are no any restrictions to doing so since it's based purely with interfaces. But it's highly unlikely to be used with C# since we have the concept of delegates there, which is straightforward and less work for the developers.
Generic Delegates
Func in C#
If you are a C# developer you should probably be familiar with the Func and Action delegates in C#. These two have been added to C# 3.0 as built in generic delegate types, so that you don’t have to define custom delegates every time.
Func is a generic delegate included in the System namespace. It has zero or more input parameters and one out parameter. The last parameter is considered as an out parameter. So let's see same above example with Func in C#.
- Func<int, int, int> func = (i, i1) => i + i1;
And we have overload versions of Func declared internally in C#. As follows,
- public delegate TResult Func<out TResult>();
- public delegate TResult Func<in T, out TResult>(T arg);
- public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
- public delegate TResult Func<in T1, in T2, in T3, out TResult>(T1 arg1, T2 arg2, T3 arg3);
- …..
Func functionality in Java
Since Java 1.8 we have the Java.util.Function interface (remember Java uses interfaces to send methods as parameters). We can use it like this
- Function<Employee, String> f0 = (e) -> e.toString();
This means function takes an employee instance as argument and returns string value of it
And here is how we going to execute it
- String result = f0.apply(e1);
Now the challenge is if we want to use this with multiple arguments as we do with C# Func. Unfortunately there is no similar implementation of Java.util.Function interface (I really hope it will do so in future!). So what is the solution/alternative?
Here is a way we can redeclare our own instance of Function interface with multiple arguments,
- @FunctionalInterface
- public interface Func<T, R> {
- R apply(T t);
- }
Likewise we can declare other instances of interface with a variable number of arguments.
- @FunctionalInterface
- public interface Func2Args<T, T1, R> {
- R apply(T t, T1 t1);
- }
-
- @FunctionalInterface
- public interface Func3Args<T,T1,T2,R> {
- R apply(T t, T1 t1, T2 t2);
- }
You may find all the relevant source code for both Java and C# in respective zip files attached to the article.
Cheers!