# Notes: Go Design Patterns - Strategy Pattern

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{})
}
```
