forked from ardanlabs/gotraining
-
Notifications
You must be signed in to change notification settings - Fork 1
/
exercise1.go
151 lines (120 loc) · 4.09 KB
/
exercise1.go
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// All material is licensed under the Apache License Version 2.0, January 2004
// http://www.apache.org/licenses/LICENSE-2.0
// Using the template, declare a set of concrete types that implement the set
// of predefined interface types. Then create values of these types and use
// them to complete a set of predefined tasks.
package main
// Add import(s).
import "fmt"
// administrator represents a person or other entity capable of administering
// hardware and software infrastructure.
type administrator interface {
administrate(system string)
}
// developer represents a person or other entity capable of writing software.
type developer interface {
develop(system string)
}
// =============================================================================
// adminlist represents a group of administrators.
type adminlist struct {
list []administrator
}
// pushAdmin adds an administrator to the adminlist.
func (l *adminlist) pushAdmin(a administrator) {
l.list = append(l.list, a)
}
// popAdmin removes an administrator from the adminlist.
func (l *adminlist) popAdmin() administrator {
a := l.list[0]
l.list = l.list[1:]
return a
}
// =============================================================================
// devlist represents a group of developers.
type devlist struct {
list []developer
}
// pushDev adds a developer to the devlist.
func (l *devlist) pushDev(d developer) {
l.list = append(l.list, d)
}
// popDev removes a developer from the devlist.
func (l *devlist) popDev() developer {
d := l.list[0]
l.list = l.list[1:]
return d
}
// =============================================================================
// Declare a concrete type named sysadmin with a name field of type string.
type sysadmin struct {
name string
}
// Declare a method named administrate for the sysadmin type, implementing the
// administrator interface. administrate should print out the name of the
// sysadmin, as well as the system they are administering.
func (s *sysadmin) administrate(system string) {
fmt.Println(s.name, "is administering", system)
}
// Declare a concrete type named programmer with a name field of type string.
type programmer struct {
name string
}
// Declare a method named develop for the programmer type, implementing the
// developer interface. develop should print out the name of the
// programmer, as well as the system they are coding.
func (p *programmer) develop(system string) {
fmt.Println(p.name, "is developing", system)
}
// Declare a concrete type named company. Declare it as the composition of
// the administrator and developer interface types.
type company struct {
administrator
developer
}
// =============================================================================
func main() {
// Create a variable named admins of type adminlist.
var admins adminlist
// Create a variable named devs of type devlist.
var devs devlist
// Push a new sysadmin onto admins.
admins.pushAdmin(&sysadmin{"John"})
// Push two new programmers onto devs.
devs.pushDev(&programmer{"Mary"})
devs.pushDev(&programmer{"Steve"})
// Create a variable named cmp of type company, and initialize it by
// hiring (popping) an administrator from admins and a developer from devs.
cmp := company{
administrator: admins.popAdmin(),
developer: devs.popDev(),
}
// Push the company value on both lists since the company implements
// each interface.
admins.pushAdmin(&cmp)
devs.pushDev(&cmp)
// A set of tasks for administrators and developers to perform.
tasks := []struct {
needsAdmin bool
system string
}{
{needsAdmin: false, system: "xenia"},
{needsAdmin: true, system: "pillar"},
{needsAdmin: false, system: "omega"},
}
// Iterate over tasks.
for _, task := range tasks {
// Check if the task needs an administrator else use a developer.
if task.needsAdmin {
// Pop an administrator value from the admins list and
// call the administrate method.
admin := admins.popAdmin()
admin.administrate(task.system)
} else {
// Pop a developer value from the devs list and
// call the develop method.
dev := devs.popDev()
dev.develop(task.system)
}
}
}