fork(1) 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. }
  36.  
  37. func NewDoor() *Door {
  38. d := new(Door)
  39. d.knob = NewKnob(d)
  40. d.closed = true
  41. return d
  42. }
  43.  
  44. func (d *Door) Knob() *Knob {
  45. return d.knob
  46. }
  47.  
  48. func (d *Door) IsClose() bool {
  49. return d.closed
  50. }
  51.  
  52. func (d *Door) IsOpen() bool {
  53. return !d.closed
  54. }
  55.  
  56. func (d *Door) CanBeOpen() bool {
  57. return d.IsOpen() || d.knob.IsLatchedOff()
  58. }
  59.  
  60. func (d *Door) Push() {
  61. if d.CanBeOpen() { d.closed = false }
  62. }
  63.  
  64. func (d *Door) Pull() {
  65. d.closed = true
  66. d.knob.Unturn()
  67. }
  68.  
  69. type DoorCloserPull struct {
  70. door DoorWithCloserer
  71. Done bool
  72. }
  73.  
  74. type DoorWithCloserer interface {
  75. Delay() int
  76. Pull()
  77. }
  78.  
  79. func NewDoorCloserPull(d DoorWithCloserer) *DoorCloserPull {
  80. p := new(DoorCloserPull)
  81. p.door = d
  82. p.Done = false
  83. return p
  84. }
  85.  
  86. func (p *DoorCloserPull) Start() {
  87. time.Sleep(time.Duration(p.door.Delay()) * time.Millisecond)
  88. if !p.Done { p.door.Pull() }
  89. }
  90.  
  91. type DoorWithCloser struct {
  92. delay int
  93. delayedPull *DoorCloserPull
  94. *Door
  95. }
  96.  
  97. func NewDoorWithCloser() *DoorWithCloser {
  98. d := new(DoorWithCloser)
  99. d.Door = NewDoor()
  100. d.delay = 300
  101. return d
  102. }
  103.  
  104. func (d *DoorWithCloser) Delay() int {
  105. return d.delay
  106. }
  107.  
  108. func (d *DoorWithCloser) Push() {
  109. d.Door.Push()
  110. if d.delayedPull != nil && !d.delayedPull.Done {
  111. d.delayedPull.Done = true
  112. }
  113. d.delayedPull = NewDoorCloserPull(d)
  114. go d.delayedPull.Start()
  115. }
  116.  
  117. type DoorWithStopper struct {
  118. *Door
  119. Stoppered bool
  120. }
  121.  
  122. func (d *DoorWithStopper) BeStopperedOn() {
  123. d.Stoppered = true
  124. }
  125.  
  126. func (d *DoorWithStopper) BeStopperedOff() {
  127. d.Stoppered = false
  128. }
  129.  
  130. func (d *DoorWithStopper) Pull() {
  131. if !d.Stoppered { d.Door.Pull() }
  132. }
  133.  
  134. func (d *DoorWithStopper) Push() {
  135. d.Stoppered = false
  136. d.Door.Push()
  137. }
  138.  
  139. func NewDoorWithStopper() *DoorWithStopper {
  140. d := new(DoorWithStopper)
  141. d.Stoppered = false
  142. d.Door = NewDoor()
  143. return d
  144. }
  145.  
  146. type DoorWithCloserStopper struct {
  147. *DoorWithCloser
  148. *DoorWithStopper
  149. }
  150.  
  151. func NewDoorWithCloserStopper() *DoorWithCloserStopper {
  152. d := new(DoorWithCloserStopper)
  153. d.DoorWithCloser = NewDoorWithCloser()
  154. d.DoorWithStopper = NewDoorWithStopper()
  155. d.DoorWithCloser.Door = d.DoorWithStopper.Door
  156. return d
  157. }
  158.  
  159. func (d *DoorWithCloserStopper) BeStopperedOff() {
  160. d.Push()
  161. }
  162.  
  163. func (d *DoorWithCloserStopper) Pull() {
  164. d.DoorWithStopper.Pull()
  165. }
  166.  
  167. func (d *DoorWithCloserStopper) Push() {
  168. d.DoorWithStopper.Push()
  169. if d.delayedPull != nil && !d.delayedPull.Done {
  170. d.delayedPull.Done = true
  171. }
  172. d.delayedPull = NewDoorCloserPull(d)
  173. go d.delayedPull.Start()
  174. }
  175.  
  176. func (d *DoorWithCloserStopper) Knob() *Knob {
  177. return d.DoorWithCloser.Knob()
  178. }
  179.  
  180. func (d *DoorWithCloserStopper) IsOpen() bool {
  181. return d.DoorWithCloser.IsOpen()
  182. }
  183.  
  184. func (d *DoorWithCloserStopper) IsClose() bool {
  185. return d.DoorWithCloser.IsClose()
  186. }
  187.  
  188. func (d *DoorWithCloserStopper) CanBeOpen() bool {
  189. return d.DoorWithCloser.CanBeOpen()
  190. }
  191.  
  192. func main(){
  193. door := NewDoor()
  194. fmt.Println("door is a Door...")
  195. door.Knob().Turn()
  196. fmt.Println("door.Knob().Turn(); door.CanBeOpen() =>", door.CanBeOpen())
  197. door.Knob().Unturn()
  198. fmt.Println("door.Knob().Unturn(); door.CanBeOpen() =>", door.CanBeOpen())
  199. door.Push()
  200. fmt.Println("door.Push(); door.IsOpen() =>", door.IsOpen())
  201. door.Knob().Turn(); door.Push()
  202. fmt.Println("door.Knob().Turn(); door.Push(); door.IsOpen() =>", door.IsOpen())
  203. door.Pull()
  204. fmt.Println("door.Pull(); door.IsClose() => ", door.IsClose())
  205. fmt.Println("door.CanBeOpen() =>", door.CanBeOpen())
  206. fmt.Println()
  207.  
  208. door2 := NewDoorWithCloser()
  209. fmt.Println("door2 is a DoorWithCloser...")
  210. door2.Knob().Turn(); door2.Push()
  211. fmt.Println("door2.Knob().Turn(); door2.Push(); door2.IsOpen() =>", door2.IsOpen())
  212. fmt.Print("0.1 second after")
  213. time.Sleep(100 * time.Millisecond)
  214. fmt.Println(", door2.IsOpen() =>", door2.IsOpen())
  215. fmt.Print("0.4 seconds after")
  216. time.Sleep(300 * time.Millisecond)
  217. fmt.Println(", door2.IsOpen() =>", door2.IsOpen())
  218. fmt.Println()
  219.  
  220. door3 := NewDoorWithStopper()
  221. fmt.Println("door3 is a DoorWithStopper...")
  222. door3.Knob().Turn(); door3.Push()
  223. fmt.Println("door3.Knob().Turn(); door3.Push(); door3.IsOpen() =>", door3.IsOpen())
  224. door3.BeStopperedOn(); door3.Pull()
  225. fmt.Println("door3.BeStopperedOn(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  226. door3.BeStopperedOff(); door3.Pull()
  227. fmt.Println("door3.BeStopperedOff(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  228. door3.Knob().Turn(); door3.Push()
  229. fmt.Println("door3.Knob().Turn(); door3.Push(); door3.IsOpen() =>", door3.IsOpen())
  230. door3.BeStopperedOn(); door3.Pull()
  231. fmt.Println("door3.BeStopperedOn(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  232. door3.Push(); door3.Pull()
  233. fmt.Println("door3.Push(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
  234. fmt.Println()
  235.  
  236. door4 := NewDoorWithCloserStopper()
  237. fmt.Println("door4 is a DoorWithCloserStopper...")
  238. door4.Knob().Turn(); door4.Push()
  239. fmt.Println("door4.Knob().Turn(); door4.Push(); door4.IsOpen() =>", door4.IsOpen())
  240. door4.BeStopperedOn()
  241. fmt.Print("door4.BeStopperedOn(); 0.4 seconds after")
  242. time.Sleep(400 * time.Millisecond)
  243. fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
  244. door4.BeStopperedOff()
  245. fmt.Print("door4.BeStopperedOff(); 0.4 seconds after")
  246. time.Sleep(400 * time.Millisecond)
  247. fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
  248. door4.Knob().Turn(); door4.Push()
  249. fmt.Println("door4.Knob().Turn(); door4.Push(); door4.IsOpen() =>", door4.IsOpen())
  250. door4.BeStopperedOn()
  251. fmt.Print("door4.BeStopperedOn(); 0.4 seconds after")
  252. time.Sleep(400 * time.Millisecond)
  253. fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
  254. door4.Push()
  255. fmt.Print("door4.Push(); 0.4 seconds after")
  256. time.Sleep(400 * time.Millisecond)
  257. fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
  258. }
  259.  
Success #stdin #stdout 0s 3000KB
stdin
Standard input is empty
stdout
door is a Door...
door.Knob().Turn(); door.CanBeOpen() => true
door.Knob().Unturn(); door.CanBeOpen() => false
door.Push(); door.IsOpen() => false
door.Knob().Turn(); door.Push(); door.IsOpen() => true
door.Pull(); door.IsClose() =>  true
door.CanBeOpen() => false

door2 is a DoorWithCloser...
door2.Knob().Turn(); door2.Push(); door2.IsOpen() => true
0.1 second after, door2.IsOpen() => true
0.4 seconds after, door2.IsOpen() => false

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...
door4.Knob().Turn(); door4.Push(); door4.IsOpen() => true
door4.BeStopperedOn(); 0.4 seconds after, door4.IsOpen() => true
door4.BeStopperedOff(); 0.4 seconds after, door4.IsOpen() => false
door4.Knob().Turn(); door4.Push(); door4.IsOpen() => true
door4.BeStopperedOn(); 0.4 seconds after, door4.IsOpen() => true
door4.Push(); 0.4 seconds after, door4.IsOpen() => false