Design Pattern in Go (Behavioral Pattern)

Posted by Sherlock Blaze on 2019-12-06

Strategy Design Pattern

The Strategy Pattern uses different algorithms to achieve some specific functionality. These algorithms are hidden behind an interface and, of course, they must be interchangeable.

Objectives

The pattern should do the following:

  • Provide a few algorithms to achieve some specific functionality.
  • All types achieve the same functionality in a different way but the client of the strategy isn’t affected.

  • example-1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package main

import (
"flag"
"fmt"
"image"
"image/color"
"image/draw"
"image/jpeg"
"log"
"os"
)

type OutputStrategy interface {
Draw() error
}

type TextSquare struct{}

func (t *TextSquare) Draw() error {
println("Circle")
return nil
}

type ImageSquare struct {
DestinationFilePath string
}

func (t ImageSquare) Draw() error {
width := 800
height := 600

bgColor := image.Uniform{color.RGBA{R: 70, G: 70, B: 70, A: 0}}
origin := image.Point{0, 0}
quality := &jpeg.Options{Quality: 75}

bgRectangle := image.NewRGBA(image.Rectangle{
Min: origin,
Max: image.Point{X: width, Y: height},
})

draw.Draw(bgRectangle, bgRectangle.Bounds(), &bgColor, origin, draw.Src)

squareWidth := 200
squareHeight := 200
squareColor := image.Uniform{color.RGBA{R: 255, G: 0, B: 0, A: 1}}
square := image.Rect(0, 0, squareWidth, squareHeight)
square = square.Add(image.Point{
X: (width / 2) - (squareWidth / 2),
Y: (width / 2) - (squareHeight / 2),
})
squareImg := image.NewRGBA(square)

draw.Draw(bgRectangle, squareImg.Bounds(), &squareColor, origin, draw.Src)

w, err := os.Create(t.DestinationFilePath)
if err != nil {
return fmt.Errorf("Error opening image")
}
defer w.Close()

if err = jpeg.Encode(w, bgRectangle, quality); err != nil {
return fmt.Errorf("Error writing image to disk")
}

return nil
}

var output = flag.String("output", "console", "The output to use between 'console' and 'image' file")

func main() {
flag.Parse()

var activeStrategy OutputStrategy

switch *output {
case "console":
activeStrategy = &TextSquare{}
case "image":
activeStrategy = &ImageSquare{"/tmp/image.jpg"}
default:
activeStrategy = &TextSquare{}
}

err := activeStrategy.Draw()
if err != nil {
log.Fatal(err)
}
}