Notes: Go Design Patterns - Strategy Pattern

Notes: Go Design Patterns - Strategy Pattern

This blog contains the implementation of Strategy design pattern using logger example on console and file

ยท

2 min read

Table of contents

No heading

No headings in the article.

Strategy pattern allows change of class or behavior of an object at runtime. Objects with similar functionalities implement a common interface. Now, we pass this interface to methods or other places which use these objects. Now, we don't care what kind of object we are passing, we can have different objects or even change objects in operation during runtime without any hassle.

Let's talk about our example. Here, we want to implement logging, console-based and file-based. Logger interface contains Log method, and console-based logging object and file-based logging object implement this method:

type LogToConsole struct{}

func (l *LogToConsole) Log(message string) {
    fmt.Println(message)
}
type LogToFile struct{}

func (l *LogToFile) Log(message string) {
    f, err := os.OpenFile(logFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
    if err != nil {
        panic(err)
    }

    defer f.Close()

    if _, err = f.WriteString(message); err != nil {
        panic(err)
    }
}

Now we pass Logger interface as a parameter in checkLogger function and it executes Log method without knowing anything about its concrete object.

func checkLogger(message string, logger Logger) {
    logger.Log(message)
}

Try running this example to understand better:

package main

import (
    "fmt"
    "os"
)

const logFile = "log.txt"

type Logger interface {
    Log(message string)
}

type LogToConsole struct{}

func (l *LogToConsole) Log(message string) {
    fmt.Println(message)
}

type LogToFile struct{}

func (l *LogToFile) Log(message string) {
    f, err := os.OpenFile(logFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
    if err != nil {
        panic(err)
    }

    defer f.Close()

    if _, err = f.WriteString(message); err != nil {
        panic(err)
    }
}

func checkLogger(message string, logger Logger) {
    logger.Log(message)
}

func main() {
    checkLogger("log to file\n", &LogToFile{})
    checkLogger("log to console", &LogToConsole{})
}
ย