06/04/2020 - GO
Go is not an object-oriented programming language but we can still replicate some patterns in it. In this example we are going to see strategy design pattern example. Strategy design pattern behaves like if ... else
and switch ... case
statements so you give something to it, it knows what exactly to do with it.
internal/
├── cache
│ ├── cache.go
│ ├── file.go
│ ├── redis.go
│ ├── session.go
│ └── strategy.go
└── main.go
package cache
import "fmt"
type File struct {}
func (File) push(key, value string, ttl int64) error {
fmt.Println("Pushing [", key, ":", value, "] to file...")
return nil
}
func (File) pop(key string) error {
fmt.Println("Popping [", key, "] from file...")
return nil
}
package cache
import "fmt"
type Redis struct {}
func (Redis) push(key, value string, ttl int64) error {
fmt.Println("Pushing [", key, ":", value, "] to redis...")
return nil
}
func (Redis) pop(key string) error {
fmt.Println("Popping [", key, "] from redis...")
return nil
}
package cache
import "fmt"
type Session struct {}
func (Session) push(key, value string, ttl int64) error {
fmt.Println("Pushing [", key, ":", value, "] to session...")
return nil
}
func (Session) pop(key string) error {
fmt.Println("Popping [", key, "] from session...")
return nil
}
This is the one all the strategies implement.
package cache
type strategy interface {
push(key, value string, ttl int64) error
pop(key string) error
}
This is the one we interact with in our code.
package cache
type Cache struct {
Strategy strategy
}
func (c *Cache) Push(key, value string, ttl int64) error {
return c.Strategy.push(key, value, ttl)
}
func (c *Cache) Pop(key string) error {
return c.Strategy.pop(key)
}
As you can see below, we can use any cache mechanism without changing the code at all. All we have to do is, pick a cache strategy. That's the whole point of the strategy pattern.
package main
import (
"log"
"internal/cache"
)
func main() {
var c = &cache.Cache{}
c.Strategy = cache.File{}
if err := c.Push("key-f", "value-f", 3600); err != nil {
log.Fatalln(err)
}
c.Strategy = cache.Redis{}
if err := c.Pop("key-r"); err != nil {
log.Fatalln(err)
}
c.Strategy = cache.Session{}
if err := c.Push("key-s", "value-s", 3600); err != nil {
log.Fatalln(err)
}
}
Pushing [ key-f : value-f ] to file...
Popping [ key-r ] from redis...
Pushing [ key-s : value-s ] to session...