Core Java

Java 8 Lambda Expression for Design Patterns – Command Design Pattern

In this blog I would illustrate implementing the command pattern in functional programming style using Java 8 Lambda expressions. The intent of command pattern is to encapsulate a request as an object, thereby parameterizing clients with different requests, queue or log requests, and support corresponding operations. The command pattern is a way of writing generic code that sequences and executes methods based on run-time decisions. The participants in this pattern are following:
 
 
 
 

  • Command – Declares an interface for executing an operation.
  • ConcreteCommand – Defines a binding between a Receiver object and an action.
  • Client – Creates a ConcreteCommand instance and sets its receiver.
  • Invoker – Controls the command(s) to carry out the request(s).
  • Receiver – Performs the actual work.

The relationship between these participants is depicted below:

commandpattern

Let’s look at a concrete example of the command pattern and see how it gets transformed with lambda expressions. Suppose we have a file system utility that has actions upon it that we’ll be calling, such as opening a file, writing to the file and closing the file. This can be implemented as macro functionality – that is, a series of operations that can be recorded and then run later as a single operation. This would be our receiver.

public interface FileSystemReceiver {
	void openFile();
	void writeFile();
        void closeFile();
}

Each of the operations, such as openFile and writefile, are commands. We can create a generic command interface to fit these different operations into. Let’s call this interface Action, as it represents performing a single action within our domain. This is the interface that all our command objects implement.

public interface Action {
    public void perform();
}

Let us now implement our Action interface for each of the operations. All these classes need to do is call a single method on FileReceiver and wrap this call into our Action interface. Lets name the classes after the operations that they wrap, with the appropriate class naming convention – so, the openFile method corresponds to a class called OpenFile.

public class OpenFile implements Action {

    private final FileReceiver fileReceiver;

    public OpenFile(FileReceiver fileReceiver) {
        this.fileReceiver = fileReceiver;
    }

    public void perform() {
        fileReceiver.openFile();
    }

}

Now let’s implement our Macro class. A macro consists of a sequence of actions that can be invoked in turn and this will act as invoker. This class can record actions and run them collectively. We can store the sequence of actions in a List then iteratively fetch each action in order to execute.

public class Macro {
    private final List actions;

    public Macro() {
        actions = new ArrayList<>();
    }

    public void record(Action action) {
        actions.add(action);
    }

    public void run() {
        actions.forEach(Action::perform);
    }
}

While populating the macros, we can add instance of each command that has been recorded to the Macro object. Now simply running the macro will call each of the commands in turn. This is our client code.

Macro macro = new Macro();
macro.record(new OpenFile(fileReceiver));
macro.record(new WriteFile(fileReceiver));
macro.record(new CloseFile(fileReceiver));
macro.run();

If you have been with me till this point, you would be wondering where lambda expressions fit in all this. Actually, all our command classes, such as OpenFile, WriteFile and CloseFile, are really just lambda expressions wanting to break out of their wrappers. They are just some behavior that is being passed around as classes. This entire pattern becomes a lot simpler with lambda expressions because we can completely do away with these classes. Let’s see how Macro class (client) can use lambda expressions instead of command classes.

Macro macro = new Macro();
macro.record(() -> fileReceiver.openFile());
macro.record(() -> fileReceiver.writeFile());
macro.record(() -> fileReceiver.closeFile());
macro.run();

This can be further improved by taking cognizance of the fact that each of these lambda expressions is performing a single method call. So, method references can be directly used.

Macro macro = new Macro();
macro.record(fileReceiver::openFile);
macro.record(fileReceiver::writeFile);
macro.record(fileReceiver::closeFile);
macro.run();

Command pattern is easily extendable and new action methods can be added in receivers to create new Command implementations without changing the client code. Runnable interface (java.lang.Runnable) in JDK is a popular interface where the Command pattern is used. In this blog, I have tried to express command pattern in Java 8 lambda expression. You would have seen by using lambda expressions, a lot less boilerplate is required leading to cleaner code.

This post has been inspired by the article Using the command pattern with lambda expressions by Richard Warburton.

Gurpreet Sachdeva

Gurpreet is a technical leader with deep hands-on experience, and passion for building software with delightful customer experience. He is passionate about building large enterprise, cloud scale, and customer centric software.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Reiner Zofall
Reiner Zofall
8 years ago

Your article looks very similar to this one by Richard Warburton:
http://radar.oreilly.com/2014/12/using-the-command-pattern-with-lambda-expressions.html

ranjan
ranjan
8 years ago
Reply to  Reiner Zofall

A little bit too similar!

Back to top button