Skip to content

Commit 741b416

Browse files
committed
add new decorator pattern
1 parent 759065a commit 741b416

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111

1212
## [Structural](structural)
1313

14-
* [Composite](structural/composite) [:notebook:](http://en.wikipedia.org/wiki/Composite_pattern)
15-
* [Binary Tree compositions](structural/binary-tree-compositions) [:notebook:](https://en.wikipedia.org/wiki/Binary_tree)
1614
* [Adapter](structural/adapter) [:notebook:](https://en.wikipedia.org/wiki/Adapter_pattern)
15+
* [Binary Tree compositions](structural/binary-tree-compositions) [:notebook:](https://en.wikipedia.org/wiki/Binary_tree)
1716
* [Bridge](structural/bridge) [:notebook:](https://en.wikipedia.org/wiki/Bridge_pattern)
18-
* [Proxy](structural/proxy) [:notebook:](https://it.wikipedia.org/wiki/Proxy_pattern)
17+
* [Composite](structural/composite) [:notebook:](http://en.wikipedia.org/wiki/Composite_pattern)
18+
* [Decorator](structural/decorator) [:notebook:](https://en.wikipedia.org/wiki/Decorator_pattern)
19+
* [Proxy](structural/proxy) [:notebook:](https://en.wikipedia.org/wiki/Proxy_pattern)

structural/decorator/README.md

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Decorator
2+
3+
The decorator pattern provide a lot of benefits when working with legacy code. In this example I have a legacy code. For example a legacy recipe. A decorator add functionality. The functionality in this example is the method Decorate. In the real world Decorate() is represented by a method that must be decorate.
4+
5+
```go
6+
type LegacyRecipe struct {
7+
Decorate() (string, error)
8+
}
9+
10+
func (lr *LegacyRecipe) Decorate() (string, error) {
11+
return "Legacy recipe with the following ingredients:", nil
12+
}
13+
```
14+
15+
All object needed to implement the decorator pattern should implement same interface.
16+
17+
```go
18+
type Decorable interface {
19+
Decorate() (string, error)
20+
}
21+
```
22+
23+
Because of we are treating with a legacy recipe. All new ingredient must contains a `Decorable` recipe.
24+
25+
```go
26+
type NewIngredient struct {
27+
recipe Decorable
28+
}
29+
30+
func (ni *NewIngredient) Decorate() (string, error) {
31+
if ni.recipe == nil {
32+
return "", errors.New("decorable recipe is needed")
33+
}
34+
s, err := ni.recipe.Decorate()
35+
if err != nil {
36+
return "", err
37+
}
38+
return fmt.Sprintf("%s %s,", s, "new ingredient"), nil
39+
}
40+
```

structural/decorator/decorator.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package decorator
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
)
7+
8+
type LegacyRecipe struct {
9+
}
10+
11+
type Decorable interface {
12+
Decorate() (string, error)
13+
}
14+
15+
type NewIngredient struct {
16+
recipe Decorable
17+
}
18+
19+
func (lr *LegacyRecipe) Decorate() (string, error) {
20+
return "Legacy recipe with the following ingredients:", nil
21+
}
22+
23+
func (ni *NewIngredient) Decorate() (string, error) {
24+
if ni.recipe == nil {
25+
return "", errors.New("decorable recipe is needed")
26+
}
27+
s, err := ni.recipe.Decorate()
28+
if err != nil {
29+
return "", err
30+
}
31+
return fmt.Sprintf("%s %s,", s, "new ingredient"), nil
32+
}
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package decorator
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
)
8+
9+
func TestNewIngredientCannotBeInstantiateWithotDecorableObject(t *testing.T) {
10+
ni := &NewIngredient{}
11+
niResult, err := ni.Decorate()
12+
if err == nil {
13+
t.Errorf(
14+
"Decorator cant decorate "+
15+
"without legacy object, "+
16+
"not a string with '%s'",
17+
niResult,
18+
)
19+
}
20+
}
21+
22+
func TestNewIngredientMustReturnDefaultText(t *testing.T) {
23+
ni := &NewIngredient{&LegacyRecipe{}}
24+
niResult, _ := ni.Decorate()
25+
if !strings.Contains(niResult, "new ingredient") {
26+
t.Errorf(
27+
"Legacy object must contains 'new ingredient', not '%s'",
28+
niResult,
29+
)
30+
}
31+
32+
fmt.Println(niResult)
33+
}

0 commit comments

Comments
 (0)