Command Pattern in Groovy using Closures
Command Pattern is one of the design patterns published in the GoF book. Command pattern is essentially encapsulating various types of request under a unified interface. The goal here is to minimise the coupling between executor and the client, with the system retaining the ability to evolve with new commands.
In a class-based language, Command Pattern is a glorified one.
interface Command {
def execute()
}
class CommandOne implements Command {
@Override
def execute() {
println "Executing Command One"
}
}
class CommandTwo implements Command {
@Override
def execute() {
println "Executing Command Two"
}
}
def executeCommand(Command command) {
command.execute()
}
executeCommand(new CommandOne()) // Executing Command One
executeCommand(new CommandTwo()) // Executing Command Two
The above code demonstrates implementing Command Pattern using a typical class-based approach. Since the executor is programmed against the Command
interface, a client can add a new Command without modifying the executor.
Groovy has closures, which are higher order - they can be passed as arguments to methods and closures. Hence instead of representing the commands as classes, we have the option of choosing to express them as closures. Let's refactor our class-based example to use closures.
You may take a look at my post on higher order functions, if you are not already familiar with the concept.
def commandOne = {
println "Executing Command One"
}
def commandTwo = {
println "Executing Command Two"
}
def executeCommand(def command) {
command()
}
executeCommand(commandOne) // Executing Command One
executeCommand(commandTwo) // Executing Command Two
Can it be that simple? Yes, we managed to achieve the same functionality as implemented in the class-based example using closures. As you can see, the code is very concise and co-located making it easier to understand and modify. Also, the second solution requires fewer building blocks of the language.
In a language with support for higher order functions, Command Pattern is a straight forward thing to implement.