Skip to content

Commit d69f990

Browse files
authored
Merge pull request #22 from bvwells/state
Implement state design pattern #15
2 parents e36e678 + 5281a3f commit d69f990

File tree

3 files changed

+105
-1
lines changed

3 files changed

+105
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Name | Description | Status
6868
[`Mediator`](./behavioral/mediator.go) | Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it allows their interaction to vary independently. |
6969
[`Memento`](./behavioral/memento.go) | Without violating encapsulation, capture and externalize an object's internal state allowing the object to be restored to this state later. |
7070
[`Observer`](./behavioral/observer.go) | Define a one-to-many dependency between objects where a state change in one object results in all its dependents being notified and updated automatically. | Implemented
71-
[`State`](./behavioral/state.go) | Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. |
71+
[`State`](./behavioral/state.go) | Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. | Implemented
7272
[`Strategy`](./behavioral/strategy.go) | Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. | Implemented
7373
[`Template Method`](./behavioral/template_method.go) | Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. | Implemented
7474
[`Visitor`](./behavioral/visitor.go) | Represent an operation to be performed on the elements of an object structure. Visitor lets a new operation be defined without changing the classes of the elements on which it operates. | Implemented

behavioral/state.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,77 @@
11
package behavioral
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// Machine defines a machine which can be swwitched on and off.
8+
type Machine struct {
9+
current State
10+
}
11+
12+
// NewMachine creates a new machine.
13+
func NewMachine() *Machine {
14+
fmt.Fprintf(outputWriter, "Machine is ready.\n")
15+
return &Machine{NewOFF()}
16+
}
17+
18+
// setCurrent sets the current state of the machine.
19+
func (m *Machine) setCurrent(s State) {
20+
m.current = s
21+
}
22+
23+
// On pushes the on button.
24+
func (m *Machine) On() {
25+
m.current.On(m)
26+
}
27+
28+
// Off pushes the off button.
29+
func (m *Machine) Off() {
30+
m.current.Off(m)
31+
}
32+
33+
// State describes the internal state of the machine.
34+
type State interface {
35+
On(m *Machine)
36+
Off(m *Machine)
37+
}
38+
39+
// ON describes the on button state.
40+
type ON struct {
41+
}
42+
43+
// NewON creates a new ON state.
44+
func NewON() State {
45+
return &ON{}
46+
}
47+
48+
// On does nothing.
49+
func (o *ON) On(m *Machine) {
50+
fmt.Fprintf(outputWriter, " already ON\n")
51+
}
52+
53+
// Off switches the state from on to off.
54+
func (o *ON) Off(m *Machine) {
55+
fmt.Fprintf(outputWriter, " going from ON to OFF\n")
56+
m.setCurrent(NewOFF())
57+
}
58+
59+
// OFF describes the off button state.
60+
type OFF struct {
61+
}
62+
63+
// NewOFF creates a new OFF state.
64+
func NewOFF() State {
65+
return &OFF{}
66+
}
67+
68+
// On switches the state from off to on.
69+
func (o *OFF) On(m *Machine) {
70+
fmt.Fprintf(outputWriter, " going from OFF to ON\n")
71+
m.setCurrent(NewON())
72+
}
73+
74+
// Off does nothing.
75+
func (o *OFF) Off(m *Machine) {
76+
fmt.Fprintf(outputWriter, " already OFF\n")
77+
}

behavioral/state_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package behavioral
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestState(t *testing.T) {
11+
12+
bufferOutputWriter := outputWriter
13+
outputWriter = new(bytes.Buffer)
14+
defer func() { outputWriter = bufferOutputWriter }()
15+
16+
machine := NewMachine()
17+
machine.Off()
18+
machine.On()
19+
machine.On()
20+
machine.Off()
21+
22+
assert.Equal(t, "Machine is ready.\n"+
23+
" already OFF\n"+
24+
" going from OFF to ON\n"+
25+
" already ON\n"+
26+
" going from ON to OFF\n", outputWriter.(*bytes.Buffer).String())
27+
28+
}

0 commit comments

Comments
 (0)