File tree 5 files changed +153
-0
lines changed
5 files changed +153
-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 different way to solve same problem. In Strategy
6
+ entire algorithm is store in different classes. In Template pattern the
7
+ algorithm is just one. The template define steps but some steps are deferred to
8
+ user.
9
+
10
+ This kind of pattern is widely used in MVC web frameworks when steps are always
11
+ the same:
12
+
13
+ - Handle Request
14
+ - Authentication
15
+ - Authorization
16
+ - Retrieve data from DB
17
+ - Do something
18
+ - Send Response
19
+
20
+ All these steps are execute for each http request. Just the ` do something `
21
+ part is defined by the user.
22
+
23
+ ## Implementation
24
+
25
+ ``` go
26
+ type TranslatorRing interface {
27
+ Next (TranslatorRing)
28
+ GetNext () TranslatorRing
29
+ KnowsWord (s string ) bool
30
+ TranslationOf (s string ) string
31
+ }
32
+ ```
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