File tree Expand file tree Collapse file tree 5 files changed +186
-0
lines changed Expand file tree Collapse file tree 5 files changed +186
-0
lines changed Original file line number Diff line number Diff line change 9
9
* [ Chain of responsiblity] ( behavioral/chain ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern )
10
10
* [ Strategy] ( behavioral/strategy ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Strategy_pattern )
11
11
* [ Command] ( behavioral/command ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Command_pattern )
12
+ * [ Template] ( behavioral/template ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Template_pattern )
12
13
13
14
## [ Creational] ( creational )
14
15
Original file line number Diff line number Diff line change @@ -7,3 +7,4 @@ We are going to deal with behaviors instead of define structures or encapsulate
7
7
* [ Strategy] ( strategy ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Strategy_pattern )
8
8
* [ Chain of Responsibility] ( chain ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern )
9
9
* [ Command] ( command ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Command_pattern )
10
+ * [ Template] ( template ) [ :notebook : ] ( https://en.wikipedia.org/wiki/Template_pattern )
Original file line number Diff line number Diff line change
1
+ # Template
2
+
3
+ ## Description
4
+
5
+ Strategy pattern consists in a different way to solve same problem with
6
+ different strategies. In Strategy entire algorithm is store in different
7
+ classes. In Template pattern, instead, the algorithm is just one. The template
8
+ defines steps but some other steps are deferred to user.
9
+
10
+ ## Implementation
11
+
12
+ In this case the template is a sort of flow of steps to solve a problem. While
13
+ in strategy pattern each strategy implements entire solution, in this case the
14
+ template define the steps execution but defer one or more steps to the user. In
15
+ this case, the deferred step is called ` templateSteps ` .
16
+
17
+ ``` go
18
+ type TheTemplate interface {
19
+ first () string
20
+ second () string
21
+ templateSteps (MessageRetriever) string
22
+ }
23
+ ```
24
+
25
+ The ` MessageRetriever ` is an interface with ` Message() ` method. The template
26
+ pattern here will joins strings. While first and third steps are implemented,
27
+ the custom step is implemented by user.
28
+
29
+ ``` go
30
+ type MessageRetriever interface {
31
+ Message () string
32
+ }
33
+ ```
34
+
35
+ Now let's implement a concrete ` Template ` .
36
+
37
+ ``` go
38
+ type Template struct {}
39
+ ```
40
+
41
+ In this case first and second steps are defined. The ` templateSteps ` will join
42
+ different strings receiving the third step from outside.
43
+
44
+ ``` go
45
+ func (t *Template ) first () string {
46
+ return " hello"
47
+ }
48
+
49
+ func (t *Template ) second () string {
50
+ return " template"
51
+ }
52
+ ```
53
+
54
+ ``` go
55
+ func (t *Template ) templateSteps (m MessageRetriever ) string {
56
+ return strings.Join (
57
+ []string {
58
+ t.first (),
59
+ m.Message (),
60
+ t.second (),
61
+ },
62
+ " " ,
63
+ )
64
+ }
65
+ ```
Original file line number Diff line number Diff line change
1
+ package template
2
+
3
+ import "strings"
4
+
5
+ type MessageRetriever interface {
6
+ Message () string
7
+ }
8
+
9
+ type TheTemplate interface {
10
+ first () string
11
+ second () string
12
+ customStep (MessageRetriever ) string
13
+ }
14
+
15
+ type Template struct {}
16
+
17
+ func (t * Template ) first () string {
18
+ return "hello"
19
+ }
20
+
21
+ func (t * Template ) second () string {
22
+ return "template"
23
+ }
24
+
25
+ func (t * Template ) customStep (m MessageRetriever ) string {
26
+ return strings .Join (
27
+ []string {
28
+ t .first (),
29
+ m .Message (),
30
+ t .second (),
31
+ },
32
+ " " ,
33
+ )
34
+ }
35
+
36
+ type Anonymous struct {}
37
+
38
+ func (a * Anonymous ) first () string {
39
+ return "hello"
40
+ }
41
+
42
+ func (a * Anonymous ) second () string {
43
+ return "template"
44
+ }
45
+
46
+ func (a * Anonymous ) customStep (f func () string ) string {
47
+ return strings .Join (
48
+ []string {
49
+ a .first (),
50
+ f (),
51
+ a .second (),
52
+ },
53
+ " " ,
54
+ )
55
+ }
56
+
57
+ type Wrapper struct {
58
+ myFunc func () string
59
+ }
60
+
61
+ func (a * Wrapper ) Message () string {
62
+ if a .myFunc != nil {
63
+ return a .myFunc ()
64
+ }
65
+
66
+ return ""
67
+ }
68
+
69
+ func MessageRetrieverAdapter (f func () string ) MessageRetriever {
70
+ return & Wrapper {myFunc : f }
71
+ }
Original file line number Diff line number Diff line change
1
+ package template
2
+
3
+ import (
4
+ "strings"
5
+ "testing"
6
+ )
7
+
8
+ type EmbedTemplate struct {
9
+ Template
10
+ }
11
+
12
+ func (m * EmbedTemplate ) Message () string {
13
+ return "world"
14
+ }
15
+
16
+ func TestCustomStepIsCalled (t * testing.T ) {
17
+ t .Run ("Using interfaces" , func (t * testing.T ) {
18
+ s := & EmbedTemplate {}
19
+ res := s .customStep (s )
20
+ check (res , " world " , t )
21
+ })
22
+
23
+ t .Run ("Define custom step via anonymous function" , func (t * testing.T ) {
24
+ m := new (Anonymous )
25
+ res := m .customStep (func () string {
26
+ return "world"
27
+ })
28
+ check (res , " world " , t )
29
+ })
30
+
31
+ t .Run ("Using anonymous functions adapted to an interface" , func (t * testing.T ) {
32
+ customStepStep := MessageRetrieverAdapter (func () string {
33
+ return "world"
34
+ })
35
+ if customStepStep == nil {
36
+ t .Fatal ("Can not continue with a nil custom step" )
37
+ }
38
+ template := Template {}
39
+ res := template .customStep (customStepStep )
40
+ check (res , " world " , t )
41
+ })
42
+ }
43
+
44
+ func check (res string , expected string , t * testing.T ) {
45
+ if ! strings .Contains (res , expected ) {
46
+ t .Errorf ("Expected string '%s' was not found on returned string '%s'\n " , expected , res )
47
+ }
48
+ }
You can’t perform that action at this time.
0 commit comments