fork download
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "time"
  6. )
  7.  
  8. type Knob struct {
  9. door *Door
  10. latched bool
  11. }
  12.  
  13. func NewKnob(d *Door) *Knob {
  14. k := new(Knob)
  15. k.door = d
  16. k.latched = true
  17. return k
  18. }
  19.  
  20. func (k *Knob) IsLatchedOff() bool {
  21. return !k.latched
  22. }
  23.  
  24. func (k *Knob) Turn() {
  25. k.latched = false
  26. }
  27.  
  28. func (k *Knob) Unturn() {
  29. if k.door.IsClose() { k.latched = true }
  30. }
  31.  
  32. type Door struct {
  33. Knob *Knob
  34. closed bool
  35. self Doorer
  36. }
  37.  
  38. type Doorer interface {
  39. IsClose() bool
  40. IsOpen() bool
  41. CanBeOpen() bool
  42. Push()
  43. Pull()
  44. Self() Doorer
  45. }
  46.  
  47. func NewDoor() *Door {
  48. d := new(Door)
  49. d.Knob = NewKnob(d)
  50. d.closed = true
  51. d.self = d
  52. return d
  53. }
  54.  
  55. func (d *Door) Self() Doorer {
  56. return d.self
  57. }
  58.  
  59. func (d *Door) IsClose() bool {
  60. return d.closed
  61. }
  62.  
  63. func (d *Door) IsOpen() bool {
  64. return !d.closed
  65. }
  66.  
  67. func (d *Door) CanBeOpen() bool {
  68. return d.IsOpen() || d.Knob.IsLatchedOff()
  69. }
  70.  
  71. func (d *Door) Push() {
  72. if d.CanBeOpen() { d.closed = false }
  73. }
  74.  
  75. func (d *Door) Pull() {
  76. d.closed = true
  77. d.Knob.Unturn()
  78. }
  79.  
  80. type DoorCloserPull struct {
  81. door DoorWithCloserer
  82. Expired bool
  83. }
  84.  
  85. type DoorWithCloserer interface {
  86. DelayMsec() int
  87. Self() Doorer
  88. }
  89.  
  90. func NewDoorCloserPull(d DoorWithCloserer) *DoorCloserPull {
  91. p := new(DoorCloserPull)
  92. p.door = d
  93. p.Expired = false
  94. return p
  95. }
  96.  
  97. func (p *DoorCloserPull) Start() {
  98. time.Sleep(time.Duration(p.door.DelayMsec()) * time.Millisecond)
  99. if !p.Expired { p.door.Self().Pull() }
  100. }
  101.  
  102. type DoorWithCloser struct {
  103. delayMsec int
  104. delayedPull *DoorCloserPull
  105. *Door
  106. }
  107.  
  108. func NewDoorWithCloser() *DoorWithCloser {
  109. d := new(DoorWithCloser)
  110. d.Door = NewDoor()
  111. d.self = d
  112. d.delayMsec = 300
  113. return d
  114. }
  115.  
  116. func (d *DoorWithCloser) DelayMsec() int {
  117. return d.delayMsec
  118. }
  119.  
  120. func (d *DoorWithCloser) SetDelayMsec(v int) {
  121. d.delayMsec = v
  122. d.ExecDelayedPull()
  123. }
  124.  
  125. func (d *DoorWithCloser) ExecDelayedPull() {
  126. if d.IsOpen() {
  127. if d.delayedPull != nil && !d.delayedPull.Expired {
  128. d.delayedPull.Expired = true
  129. }
  130. d.delayedPull = NewDoorCloserPull(d)
  131. go d.delayedPull.Start()
  132. }
  133. }
  134.  
  135. func (d *DoorWithCloser) Push() {
  136. d.Door.Push()
  137. d.ExecDelayedPull()
  138. }
  139.  
  140.  
  141. type DoorStopper struct {
  142. door DoorWithStopperer
  143. stoppered bool
  144. }
  145.  
  146. type DoorWithStopperer interface {
  147. Pull()
  148. Push()
  149. }
  150.  
  151. func NewDoorStopper(d DoorWithStopperer) *DoorStopper {
  152. s := new(DoorStopper)
  153. s.door = d
  154. s.stoppered = false
  155. return s
  156. }
  157.  
  158. func (s *DoorStopper) BeStopperedOn() {
  159. s.stoppered = true
  160. }
  161.  
  162. func (s *DoorStopper) BeStopperedOff() {
  163. s.stoppered = false
  164. }
  165.  
  166. func (s *DoorStopper) Pull() {
  167. if !s.stoppered { s.door.Pull() }
  168. }
  169.  
  170. func (s *DoorStopper) Push() {
  171. s.stoppered = false
  172. s.door.Push()
  173. }
  174.  
  175. type DoorWithStopper struct {
  176. *Door
  177. *DoorStopper
  178. }
  179.  
  180. func NewDoorWithStopper() *DoorWithStopper {
  181. d := new(DoorWithStopper)
  182. d.Door = NewDoor()
  183. d.self = d
  184. d.DoorStopper = NewDoorStopper(d.Door)
  185. return d
  186. }
  187.  
  188. func (d *DoorWithStopper) Pull() {
  189. d.DoorStopper.Pull()
  190. }
  191.  
  192. func (d *DoorWithStopper) Push() {
  193. d.DoorStopper.Push()
  194. }
  195.  
  196.  
  197. type DoorWithCloserStopper struct {
  198. *DoorWithCloser
  199. *DoorStopper
  200. }
  201.  
  202. func NewDoorWithCloserStopper() *DoorWithCloserStopper {
  203. d := new(DoorWithCloserStopper)
  204. d.DoorWithCloser = NewDoorWithCloser()
  205. d.self = d
  206. d.DoorStopper = NewDoorStopper(d.DoorWithCloser)
  207. return d
  208. }
  209.  
  210. func (d *DoorWithCloserStopper) BeStopperedOff() {
  211. d.DoorStopper.BeStopperedOff()
  212. d.ExecDelayedPull()
  213. }
  214.  
  215. func (d *DoorWithCloserStopper) Pull() {
  216. d.DoorStopper.Pull()
  217. }
  218.  
  219. func (d *DoorWithCloserStopper) Push() {
  220. d.DoorStopper.Push()
  221. }
  222.  
  223.  
  224. func main(){
  225. door1 := NewDoor()
  226. fmt.Println("door1 is a Door...")
  227. door1.Knob.Turn()
  228. fmt.Println("door1.Knob.Turn(); door1.CanBeOpen() =>", door1.CanBeOpen())
  229. door1.Knob.Unturn()
  230. fmt.Println("door1.Knob.Unturn(); door1.CanBeOpen() =>", door1.CanBeOpen())
  231. door1.Push()
  232. fmt.Println("door1.Push(); door1.IsOpen() =>", door1.IsOpen())
  233. door1.Knob.Turn(); door1.Push()
  234. fmt.Println("door1.Knob.Turn(); door1.Push(); door1.IsOpen() =>", door1.IsOpen())
  235. door1.Pull()
  236. fmt.Println("door1.Pull(); door1.IsClose() => ", door1.IsClose())
  237. fmt.Println("door1.CanBeOpen() =>", door1.CanBeOpen())
  238. fmt.Println()
  239.  
  240. door2 := NewDoorWithCloser()
  241. fmt.Println("door2 is a DoorWithCloser with", door2.DelayMsec(), "milliseconds delay...")
  242. door2.Knob.Turn(); door2.Push()
  243. fmt.Println("door2.Knob.Turn(); door2.Push(); door2.IsOpen() =>", door2.IsOpen())
  244. fmt.Print("0.1 second after")
  245. time.Sleep(100 * time.Millisecond)
  246. fmt.Println(", door2.IsOpen() =>", door2.IsOpen())
  247. fmt.Print("0.4 seconds after")
  248. time.Sleep(300 * time.Millisecond)
  249. fmt.Println(", door2.IsClose() =>", door2.IsClose())
  250. door2.Knob.Turn(); door2.Push(); door2.SetDelayMsec(600)
  251. fmt.Println("door2.Knob.Turn(); door2.Push(); door2.SetDelayMsec(600); door2.IsOpen() =>", door2.IsOpen())
  252. fmt.Print("0.4 seconds after")
  253. time.Sleep(400 * time.Millisecond)
  254. fmt.Println(", door2.IsClose() =>", door2.IsClose())
  255. fmt.Print("0.7 seconds after")
  256. time.Sleep(300 * time.Millisecond)
  257. fmt.Println(", door2.IsClose() =>", door2.IsClose())
  258. fmt.Println()
  259.  
  260. door3 := NewDoorWithStopper()
  261. fmt.Println("door3 is a DoorWithStopper...")
  262. door3.Knob.Turn(); door3.Push()
  263. fmt.Println("door3.Knob.Turn(); door3.Push(); door3.IsOpen() =>", door3.IsOpen())
  264. door3.BeStopperedOn(); door3.Pull()
  265. fmt.Println("door3.BeStopperedOn(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  266. door3.BeStopperedOff(); door3.Pull()
  267. fmt.Println("door3.BeStopperedOff(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  268. door3.Knob.Turn(); door3.Push()
  269. fmt.Println("door3.Knob.Turn(); door3.Push(); door3.IsOpen() =>", door3.IsOpen())
  270. door3.BeStopperedOn(); door3.Pull()
  271. fmt.Println("door3.BeStopperedOn(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  272. door3.Push(); door3.Pull()
  273. fmt.Println("door3.Push(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  274. fmt.Println()
  275.  
  276. door4 := NewDoorWithCloserStopper()
  277. fmt.Println("door4 is a DoorWithCloserStopper with", door4.DelayMsec(), "milliseconds delay...")
  278. door4.Knob.Turn(); door4.Push()
  279. fmt.Println("door4.Knob.Turn(); door4.Push(); door4.IsOpen() =>", door4.IsOpen())
  280. door4.BeStopperedOn()
  281. fmt.Print("door4.BeStopperedOn(); 0.4 seconds after")
  282. time.Sleep(400 * time.Millisecond)
  283. fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
  284. door4.BeStopperedOff()
  285. fmt.Print("door4.BeStopperedOff(); 0.4 seconds after")
  286. time.Sleep(400 * time.Millisecond)
  287. fmt.Println(", door4.IsClose() =>", door4.IsClose())
  288. door4.Knob.Turn(); door4.Push()
  289. fmt.Println("door4.Knob.Turn(); door4.Push(); door4.IsOpen() =>", door4.IsOpen())
  290. door4.BeStopperedOn()
  291. fmt.Print("door4.BeStopperedOn(); 0.4 seconds after")
  292. time.Sleep(400 * time.Millisecond)
  293. fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
  294. door4.Push()
  295. fmt.Print("door4.Push(); 0.4 seconds after")
  296. time.Sleep(400 * time.Millisecond)
  297. fmt.Println(", door4.IsClose() =>", door4.IsClose())
  298. }
Success #stdin #stdout 0s 3000KB
stdin
Standard input is empty
stdout
door1 is a Door...
door1.Knob.Turn(); door1.CanBeOpen() => true
door1.Knob.Unturn(); door1.CanBeOpen() => false
door1.Push(); door1.IsOpen() => false
door1.Knob.Turn(); door1.Push(); door1.IsOpen() => true
door1.Pull(); door1.IsClose() =>  true
door1.CanBeOpen() => false

door2 is a DoorWithCloser with 300 milliseconds delay...
door2.Knob.Turn(); door2.Push(); door2.IsOpen() => true
0.1 second after, door2.IsOpen() => true
0.4 seconds after, door2.IsClose() => true
door2.Knob.Turn(); door2.Push(); door2.SetDelayMsec(600); door2.IsOpen() => true
0.4 seconds after, door2.IsClose() => false
0.7 seconds after, door2.IsClose() => true

door3 is a DoorWithStopper...
door3.Knob.Turn(); door3.Push(); door3.IsOpen() => true
door3.BeStopperedOn(); door3.Pull(); door3.IsClose() => false
door3.BeStopperedOff(); door3.Pull(); door3.IsClose() => true
door3.Knob.Turn(); door3.Push(); door3.IsOpen() => true
door3.BeStopperedOn(); door3.Pull(); door3.IsClose() => false
door3.Push(); door3.Pull(); door3.IsClose() => true

door4 is a DoorWithCloserStopper with 300 milliseconds delay...
door4.Knob.Turn(); door4.Push(); door4.IsOpen() => true
door4.BeStopperedOn(); 0.4 seconds after, door4.IsOpen() => true
door4.BeStopperedOff(); 0.4 seconds after, door4.IsClose() => true
door4.Knob.Turn(); door4.Push(); door4.IsOpen() => true
door4.BeStopperedOn(); 0.4 seconds after, door4.IsOpen() => true
door4.Push(); 0.4 seconds after, door4.IsClose() => true