Design Pattern: Template Method Pattern in Go

Using Template Method Pattern we can write part of an algorithm in our implementation and the rest of it is executed in abstraction. So our implementation will replace/rewrite only some steps of the full process.

This article demonstrates Template Method pattern implementations in Golang. Check the following examples and implementation details.

Implementation

Here is a simple example of the Template Method pattern in Golang-

  • Create an interface and declare methods that we want to implement later in our implementation. This is our template interface.
  • Define a struct for the template, and embed the template interface into it. Define some steps here and define a method that executes all the steps of the full process (in the example below we have named it “process”).
  • Define some concrete implementation of the template. Embed the template struct into this. Define the methods that are declared in the template interface.

Here is a simple implementation of the Template Method in Go-

// Template method pattern implementation in Go

package main

import "fmt"

// Template interface
type ITemplate interface {
	StepA()
	StepB()
}

// Template struct
type Template struct {
	ITemplate
}

func NewTemplate(iTemplate ITemplate) (template *Template) {
	template = &Template{}
	template.ITemplate = iTemplate
	return
}

func (template *Template) StepC() {
	fmt.Println("Executing Step C of Template")
}

func (template *Template) StepD() {
	fmt.Println("Executing Step D of Template")
}

func (template *Template) Process() {
	template.ITemplate.StepA()
	template.ITemplate.StepB()
	template.StepC()
	template.StepD()
}

// Concrete implementation
type ConcreteA struct {
	*Template
}

func NewConreteA() (concreteA *ConcreteA) {
	concreteA = &ConcreteA{}
	concreteA.Template = NewTemplate(concreteA)
	return
}

func (concreteA *ConcreteA) StepA() {
	fmt.Println("Executing Step A of ConcreteA")
}

func (concreteA *ConcreteA) StepB() {
	fmt.Println("Executing Step B of ConcreteA")
}

// Concrete implementation
type ConcreteB struct {
	*Template
}

func NewConcreteB() (concreteB *ConcreteB) {
	concreteB = &ConcreteB{}
	concreteB.Template = NewTemplate(concreteB)
	return
}

func (concreteA *ConcreteB) StepA() {
	fmt.Println("Executing Step A of ConcreteB")
}

func (concreteA *ConcreteB) StepB() {
	fmt.Println("Executing Step B of ConcreteB")
}

// Demo
func main() {
	concreteA := NewConreteA()
	concreteA.Process()

	concreteB := NewConcreteB()
	concreteB.Process()
}

Output will be as below-

Executing Step A of ConcreteA
Executing Step B of ConcreteA
Executing Step C of Template
Executing Step D of Template


Executing Step A of ConcreteB
Executing Step B of ConcreteB
Executing Step C of Template
Executing Step D of Template

Examples

Here are a few examples of Template Method pattern in GoLang-

Example #1: Transport Construction

Let’s consider an example of transport construction.

Transport Interface and Struct

// transport.go

package main

import "fmt"

type ITransport interface {
	CreateBody()
	AddEngine()
	AddWheel()

	// Required only for Plane
	AddWing()
}

type Transport struct {
	ITransport
}

func NewTransport(iTransport ITransport) (transport *Transport) {
	transport = &Transport{}
	transport.ITransport = iTransport
	return
}

func (transport *Transport) AddSeat() {
	// Add seats to the vehicle

	// Adding seats are same for all transports so same functions for all
	fmt.Println("Adding seats")
}

func (transport *Transport) paint() {
	fmt.Println("Painting")
}

func (transport *Transport) Build() {
	transport.ITransport.CreateBody()
	transport.ITransport.AddEngine()
	transport.ITransport.AddWheel()
	transport.ITransport.AddWing()

	transport.AddSeat()
	transport.paint()
}

Car Transport Struct

// car.go

package main

import "fmt"

type Car struct {
	*Transport
}

func NewCar() (car *Car) {
	car = &Car{}
	car.Transport = NewTransport(car)
	return
}

func (car *Car) AddEngine() {
	fmt.Println("Adding Engine to Car")
}

func (car *Car) AddWheel() {
	fmt.Println("Adding 4 Wheels to Car")
}

func (car *Car) AddWing() {
	// implementation not require for car
}

func (car *Car) CreateBody() {
	fmt.Println("Creating Car Body")
}

Bike Transport Struct

// bike.go

package main

import "fmt"

type Bike struct {
	*Transport
}

func NewBike() (bike *Bike) {
	bike = &Bike{}
	bike.Transport = NewTransport(bike)
	return
}

func (bike *Bike) AddEngine() {
	fmt.Println("Adding Engine to Bike")
}

func (bike *Bike) AddWheel() {
	fmt.Println("Adding 2 Wheels to Bike")
}

func (bike *Bike) AddWing() {
	// Implementation not required for bike
}

func (bike *Bike) CreateBody() {
	fmt.Println("Creating Bike Body")
}

Plane Transport Struct

// plane.go

package main

import "fmt"

type Plane struct {
	*Transport
}

func NewPlane() (plane *Plane) {
	plane = &Plane{}
	plane.Transport = NewTransport(plane)
	return
}

func (plane *Plane) AddEngine() {
	fmt.Println("Adding Engine to Plane")
}

func (plane *Plane) AddWheel() {
	fmt.Println("Adding 3 Wheels to Plane")
}

func (plane *Plane) AddWing() {
	fmt.Println("Adding Wings Plane")
}

func (plane *Plane) CreateBody() {
	fmt.Println("Creating Plane Body")
}

Train Transport Struct

// train.go

package main

import "fmt"

type Train struct {
	*Transport
}

func NewTrain() (train *Train) {
	train = &Train{}
	train.Transport = NewTransport(train)
	return
}

func (train *Train) AddEngine() {
	fmt.Println("Adding Engine to Train")
}

func (train *Train) AddWheel() {
	fmt.Println("Adding Wheels to Train")
}

func (train *Train) AddWing() {
	// implementatiom not require for train
}

func (train *Train) CreateBody() {
	fmt.Println("Creating Train Body")
}

Demo

// main.go

package main

func main() {
	car := NewCar()
	car.Build()

	plane := NewPlane()
	plane.Build()
}

Output

Creating Car Body
Adding Engine to Car
Adding 4 Wheels to Car
Adding seats
Painting

Creating Plane Body
Adding Engine to Plane
Adding 3 Wheels to Plane
Adding Wings Plane
Adding seats
Painting

Source Code

Use the following link to get the source code:

Other Code Implementations

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

Leave a Comment


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