Design Pattern: Command Pattern in Go

Command pattern is used to store a full execution process in an object. The command object is independent of any other dependencies and can be executed and/or passed without any additional information.

This article demonstrates Command pattern implementations in Golang. Check the following examples.

Implementation

Follow the steps below-

  • Define an interface for ensuring a common interface for all the commands. Make sure to have methods for the execution and remove/undo the commands.
  • Define the command structs and implement the interface for those structs.
  • Create a struct for the control.
  • In the control struct, define methods for adding and removing command elements. In the methods for adding/removing call the methods from the command.
  • In the control structure, maintain a list of commands. While adding the element call the add/execution method from the command, and also add that to the list. Remove the command from the list, in case of removing the element.

Examples

Here are a few examples of Command pattern implementation in Golang.

Example #1: UI Elements

Let’s take the example of printing UI elements. Let’s take a look at the class diagram first.

Command Interface

  • Create file “ui_command.go”.
  • Create interface “UiCommand”.
  • Declare methods as per requirement – “Print”, “Remove”.
// ui_command.go

package main

type UiCommand interface {
	Print()
	Remove()
}

Button Struct

  • Create file “button_ui.go”.
  • Create struct “ButtonUi”.
  • Declare a field named “name”.
  • Create method “NewButtonUi”, this will create a new struct and return that. Also, set the value of “name”.
  • Implement the “UiCommand” interface for the struct. Define methods “Print” and “Remove” for the interface implementation.
// button_ui.go

package main

import "fmt"

type ButtonUi struct {
	name string
}

func NewButtonUi(name string) (buttonUi *ButtonUi) {
	buttonUi = &ButtonUi{}
	buttonUi.name = name
	return
}

func (buttonUi *ButtonUi) Print() {
	fmt.Printf("Printing %s Buton\n", buttonUi.name)
}

func (buttonUi *ButtonUi) Remove() {
	fmt.Printf("Removing %s Button\n", buttonUi.name)
}

Input Element Struct

  • Create file “input_ui.go”.
  • Create struct “InputUi”.
  • Create method “NewInputUi”, this will create a new struct and return that.
  • Implement the “UiCommand” interface for the struct. Define methods “Print” and “Remove” for the interface implementation.
// input_ui.go

package main

import "fmt"

type InputUi struct {
}

func NewInputUi() (inputUi *InputUi) {
	inputUi = &InputUi{}
	return
}

func (inputUi *InputUi) Print() {
	fmt.Println("Printing Input")
}

func (inputUi *InputUi) Remove() {
	fmt.Println("Removing Input")
}

Table Element Struct

  • Create file “table_ui.go”.
  • Create struct “TableUi”.
  • Create method “NewTableUi”, create a new struct, and return that.
  • Implement the “UiCommand” interface for the struct.
// table_ui.go

package main

import "fmt"

type TableUi struct {
}

func NewTableUi() (tableUi *TableUi) {
	tableUi = &TableUi{}
	return
}

func (tableUi *TableUi) Print() {
	fmt.Println("Printing Table")
}

func (tableUi *TableUi) Remove() {
	fmt.Println("Removing Table")
}

UI Element Control Struct

  • Create file “ui_control.go”.
  • Create struct “UiControl”.
  • Declare field “commandList”, a slice of “UiCommand”.
  • Create method “NewUiControl”, to create a new struct, and return that.
  • Define method “AddElement”. In the implementation add code for printing the element(call the “Print” method). Also add the command to the “commandList”.
  • Define method “RemoveElement”. In the implementation call the “Remove” method of the element, and also remove the element from “commandList”.
  • As a utility method, we have an “Undo” method here, to undo the last command. which in turn uses the “RemoveElement” method.
// ui_control.go

package main

type UiControl struct {
	commandList []UiCommand
}

func NewUiControl() (uiControl *UiControl) {
	uiControl = &UiControl{}
	return
}

func (uiControl *UiControl) AddElement(uiCommand UiCommand) {
	// Execute command
	uiCommand.Print()

	// Add to list
	uiControl.commandList = append(uiControl.commandList, uiCommand)
}

func (uiControl *UiControl) RemoveElement(uiCommand UiCommand) {
	// Remove element
	uiCommand.Remove()

	// Remove from list
	newList := []UiCommand{}

	for _, elem := range uiControl.commandList {
		if elem != uiCommand {
			newList = append(newList, elem)
		}
	}

	uiControl.commandList = newList
}

func (uiControl *UiControl) Undo() {
	uiCommand := uiControl.commandList[len(uiControl.commandList) - 1]
	uiControl.RemoveElement(uiCommand)
}

Demo

For using the implementation, create an “UiControl”. Then we can add/remove elements from that.

// main.go

package main

func main() {
	uiControl := NewUiControl()
	inputUi := NewInputUi()
	tableUi := NewTableUi()
	buttonUi := NewButtonUi("Submit")

	uiControl.AddElement(inputUi)
	uiControl.AddElement(tableUi)
	uiControl.AddElement(buttonUi)

	uiControl.RemoveElement(tableUi)

	uiControl.AddElement(NewButtonUi("Cancel"))
	uiControl.AddElement(NewTableUi())
	uiControl.AddElement(NewInputUi())
	uiControl.AddElement(NewButtonUi("Wrong button"))

	uiControl.Undo()
	uiControl.Undo()
}

Output

Output will be as below-

Printing Input
Printing Table
Printing Submit Buton

Removing Table

Printing Cancel Buton
Printing Table
Printing Input
Printing Wrong button Buton

Removing Wrong button Button
Removing Input

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Command pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.