Design Patterns in Go: The Command, a simple implementation of a versatile pattern

Introduction

The command pattern is a behavioral design pattern. It is used by an Invoker to perform one action or a series of actions on objects, called Receivers. The Invoker is unaware of the nature of the receiving objects, it just knows about the command. That way we achieve a loose coupling between Invoker and Receiver.

It looks like this:

A short breakdown of this diagram:

  • The Invoker is the object want to execute a command or a series of commands on some unknown objects, that is, the Invoker might be unaware of them.
  • The Command interface. Many classes might implement this interface.
  • In this example there is just one class implementing the Command interface, CommandA, which works on ReceiverA. As you can see, the Invoker and the Receiver are not coupled, and the only communication between the two goes via the Command.

Implementation in Go

In an empty directory, open your terminal or commandline and type:

go mod init github.com/command_pattern

Then open your favourite IDE and add a main.go file.

First we need to add these preliminaries:

package main

import "fmt"

The Command interface in this example is very simple:

type Command interface {
	Execute()
}

It only contains an Execute() method. In practice, the Command interface might be more elaborate than this.

Now implement the first Command:

type PrintCommand struct {
	Message string
}

func (p *PrintCommand) Execute() {
	fmt.Println(p.Message)
}

All the PrintCommand does, is print a message.

Now for a more complex example, the MultiplyCommand:

type MultiplyCommand struct {
	A, B int
}

func (m *MultiplyCommand) Execute() {
	result := m.A * m.B
	fmt.Printf("%d * %d = %d", m.A, m.B, result)
}

The MultiplyCommand has two integer fields, the Execute() method multiplies those, and prints the result.

So far so good, now we to be able to invoke these commands, so we will implement an Invoker struct:

type Invoker struct {
	commands []Command
}

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

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

A short breakdown:

  • The Invoker struct contains a list of commands
  • The AddCommand() method adds a struct implementing the Command interface to this list
  • The Execute() method iterates over the commands list, and executes the commands.

Time to test all of this in the main function:

func main() {
	invoker := &Invoker{}
	invoker.AddCommand(&PrintCommand{"Hello World"})
	invoker.AddCommand(&MultiplyCommand{9, 3})
	invoker.ExecuteCommands()
}

A line by line breakdown:

  1. We construct an Invoker
  2. We add an instance of the PrintCommand struct to the Invoker
  3. We add another instance of the MultiplyCommand struct to the Invoker
  4. Next we simple execute all of these commands.

As you can see in this setup, the Invoker is totally unaware of any of the Command structs.

Conclusion

The Command pattern has many uses, such as in GUI programming, Mobile code, or parallel processing. As you can see here, the implementation can be quite simple. One of my next projects will be to see how we can use this pattern concurrently in a multithreaded environment.

What you can also see is that for example the building of an Undo-facility is quite easy. This is also an exercise I will do in one of my next blogs

Leave a Reply

Your email address will not be published. Required fields are marked *