Christian Giacomi

Command design pattern in Go

Posted — May 12, 2019

Design patterns are a must know for any software developer. They are important not just because they give developers a set of tools to overcome common problems encountered while developing software, but the also give developers a common language with which to communicate with.

Classic ‘Design patterns’ are grouped in three different categories: Creational, Structural and Behavioral, as outlined in the book ‘Design Patterns: Elements of Reusable Object-Oriented Software’ by the Gang of Four.

The book is very good at categorizing each pattern and aside from the name, it outlines the problem, the solution and the consequences for each pattern.

The ‘Command’ pattern is a behavioral pattern.

“Behavioral patterns are concerned with algorithms and the assignment of responsibilities between objects. Behavioral patterns describe not just patterns of objects or classes but also the patterns of communication between them. These patterns characterize complex control flow…"

Design Patterns: Elements of Reusable Object-Oriented Software

The ‘Command’ pattern in particular encapsulates all the actions and parameters needed to carry out the work. When looking at ‘Design Patterns’ by the Gang of Four, the pattern mentions four terms, which are command, receiver, invoker and client.

Each actor in this design pattern is responsible for the following:

For more information on these terms and the pattern in general you should take a look at the book.

The following class diagram outlines the high level view of the pattern and the classes comprising the pattern.

command-pattern-class-diagram

Here is a very simple implementation in Go. I have chosen Go because the language doesn’t support all the constructs other statically typed languages do. In this case I am referring to Inheritance and Interfaces. This difference in Go makes for an interesting implementation. As you will see the majority of these patterns are usually shown in C++, Java or C#.

As you know Go does not support inheritance and unlike other statically typed languages, in Go a Type does not explicitly implement an interface like for example Java, C++, C# or Swift. Instead it’s a little (and I mean syntactically) like Python’s Duck Typing, where as long as a Type contains a method with the same signature as one defined in the interface, you can invoke such method from the interface. As such:

package main

import "fmt"

type Shape interface {
    Color() string
}

type Circle struct{}
func (c Circle) Color() string {
    return "green"
}

func main() {
    var s Shape // Interface
    s = Circle{} // Concrete Type

    fmt.Println(s.Color())
}

For a greater understanding of Interfaces in Go you should take a look at this really great blog post.

The Command pattern

The following is a simple implementation of the pattern without the ‘Receiver’ part of the pattern. Please note that the main function acts as the ‘Client’.

The interface

package command

type Command interface {
    Execute()
}

The concrete command

package command

import "fmt"

type ConcreteCommand struct{}

func (c ConcreteCommand) Execute() {
    fmt.Println("hello from a command")
}

The Invoker and Client

package main

import "command"

// Invoker represents the type that is responsible of
// executing the concrete command
type Invoker struct{}
func (i Invoker) ExecuteCommands() {
    var c command.Command // The interface

    c = command.ConcreteCommand{} // The concrete command
    c.Execute()
}


// The main function acting as the client
func main() {
    i := Invoker{}
    i.ExecuteCommands()
}

The example above is very simplistic and if you have read ‘Design Patterns’ you will immediately note that I am creating an instance of the ConcreteCommand directly within the Invoker, and this is not the way it should be done.

So let’s take a look at the revised Invoker and Client code. Ideally the Client is the one that creates the instances of the ConcreteCommand and Receiver, which it then passes onto the Invoker which is in turn responsible for actually invoking the correct command (based on the business logic of the app).

package main

import "command"

type Invoker struct {
    commands []command.Command
}

func (i *Invoker) RegisterCommand(c command.Command) {
    i.commands = append(i.commands, c)
}

func (i *Invoker) ExecuteCommands() {
    for _, cmd := range i.commands {
        cmd.Execute()
    }
}

func main() {
    // Create a ConcreteCommand but reference it from the interface
    var c command.Command = command.ConcreteCommand{}

    i := Invoker{}
    i.RegisterCommand(c)
    i.ExecuteCommands()
}

Of course the Receiver is still missing from the code, but it should be now clear how the pattern works and it’s quite simple to add a specialized Receiver should you choose to.

If this post was helpful tweet it or share it.

See Also