package main
import (
"fmt"
"time"
)
type Knob struct {
door *Door
latched bool
}
func NewKnob(d *Door) *Knob {
k := new(Knob)
k.door = d
k.latched = true
return k
}
func (k *Knob) IsLatchedOff() bool {
return !k.latched
}
func (k *Knob) Turn() {
k.latched = false
}
func (k *Knob) Unturn() {
if k.door.IsClose() { k.latched = true }
}
type Door struct {
knob *Knob
closed bool
}
func NewDoor() *Door {
d := new(Door)
d.knob = NewKnob(d)
d.closed = true
return d
}
func (d *Door) Knob() *Knob {
return d.knob
}
func (d *Door) IsClose() bool {
return d.closed
}
func (d *Door) IsOpen() bool {
return !d.closed
}
func (d *Door) CanBeOpen() bool {
return d.IsOpen() || d.knob.IsLatchedOff()
}
func (d *Door) Push() {
if d.CanBeOpen() { d.closed = false }
}
func (d *Door) Pull() {
d.closed = true
d.knob.Unturn()
}
type DoorCloserPull struct {
door DoorWithCloserer
Done bool
}
type DoorWithCloserer interface {
Delay() int
Pull()
}
func NewDoorCloserPull(d DoorWithCloserer) *DoorCloserPull {
p := new(DoorCloserPull)
p.door = d
p.Done = false
return p
}
func (p *DoorCloserPull) Start() {
time.
Sleep(time.
Duration(p.
door.
Delay()) * time.
Millisecond) if !p.Done { p.door.Pull() }
}
type DoorWithCloser struct {
delay int
delayedPull *DoorCloserPull
*Door
}
func NewDoorWithCloser() *DoorWithCloser {
d := new(DoorWithCloser)
d.Door = NewDoor()
d.delay = 300
return d
}
func (d *DoorWithCloser) Delay() int {
return d.delay
}
func (d *DoorWithCloser) Push() {
d.Door.Push()
if d.delayedPull != nil && !d.delayedPull.Done {
d.delayedPull.Done = true
}
d.delayedPull = NewDoorCloserPull(d)
go d.delayedPull.Start()
}
type DoorWithStopper struct {
*Door
Stoppered bool
}
func (d *DoorWithStopper) BeStopperedOn() {
d.Stoppered = true
}
func (d *DoorWithStopper) BeStopperedOff() {
d.Stoppered = false
}
func (d *DoorWithStopper) Pull() {
if !d.Stoppered { d.Door.Pull() }
}
func (d *DoorWithStopper) Push() {
d.Stoppered = false
d.Door.Push()
}
func NewDoorWithStopper() *DoorWithStopper {
d := new(DoorWithStopper)
d.Stoppered = false
d.Door = NewDoor()
return d
}
type DoorWithCloserStopper struct {
*DoorWithCloser
*DoorWithStopper
}
func NewDoorWithCloserStopper() *DoorWithCloserStopper {
d := new(DoorWithCloserStopper)
d.DoorWithCloser = NewDoorWithCloser()
d.DoorWithStopper = NewDoorWithStopper()
d.DoorWithCloser.Door = d.DoorWithStopper.Door
return d
}
func (d *DoorWithCloserStopper) BeStopperedOff() {
d.Push()
}
func (d *DoorWithCloserStopper) Pull() {
d.DoorWithStopper.Pull()
}
func (d *DoorWithCloserStopper) Push() {
d.DoorWithStopper.Push()
if d.delayedPull != nil && !d.delayedPull.Done {
d.delayedPull.Done = true
}
d.delayedPull = NewDoorCloserPull(d)
go d.delayedPull.Start()
}
func (d *DoorWithCloserStopper) Knob() *Knob {
return d.DoorWithCloser.Knob()
}
func (d *DoorWithCloserStopper) IsOpen() bool {
return d.DoorWithCloser.IsOpen()
}
func (d *DoorWithCloserStopper) IsClose() bool {
return d.DoorWithCloser.IsClose()
}
func (d *DoorWithCloserStopper) CanBeOpen() bool {
return d.DoorWithCloser.CanBeOpen()
}
func main(){
door := NewDoor()
fmt.Println("door is a Door...")
door.Knob().Turn()
fmt.Println("door.Knob().Turn(); door.CanBeOpen() =>", door.CanBeOpen())
door.Knob().Unturn()
fmt.Println("door.Knob().Unturn(); door.CanBeOpen() =>", door.CanBeOpen())
door.Push()
fmt.Println("door.Push(); door.IsOpen() =>", door.IsOpen())
door.Knob().Turn(); door.Push()
fmt.Println("door.Knob().Turn(); door.Push(); door.IsOpen() =>", door.IsOpen())
door.Pull()
fmt.Println("door.Pull(); door.IsClose() => ", door.IsClose())
fmt.Println("door.CanBeOpen() =>", door.CanBeOpen())
fmt.Println()
door2 := NewDoorWithCloser()
fmt.Println("door2 is a DoorWithCloser...")
door2.Knob().Turn(); door2.Push()
fmt.Println("door2.Knob().Turn(); door2.Push(); door2.IsOpen() =>", door2.IsOpen())
fmt.Print("0.1 second after")
fmt.Println(", door2.IsOpen() =>", door2.IsOpen())
fmt.Print("0.4 seconds after")
fmt.Println(", door2.IsOpen() =>", door2.IsOpen())
fmt.Println()
door3 := NewDoorWithStopper()
fmt.Println("door3 is a DoorWithStopper...")
door3.Knob().Turn(); door3.Push()
fmt.Println("door3.Knob().Turn(); door3.Push(); door3.IsOpen() =>", door3.IsOpen())
door3.BeStopperedOn(); door3.Pull()
fmt.Println("door3.BeStopperedOn(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
door3.BeStopperedOff(); door3.Pull()
fmt.Println("door3.BeStopperedOff(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
door3.Knob().Turn(); door3.Push()
fmt.Println("door3.Knob().Turn(); door3.Push(); door3.IsOpen() =>", door3.IsOpen())
door3.BeStopperedOn(); door3.Pull()
fmt.Println("door3.BeStopperedOn(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
door3.Push(); door3.Pull()
fmt.Println("door3.Push(); door3.Pull(); door3.IsClose() =>", door3.IsClose())
fmt.Println()
door4 := NewDoorWithCloserStopper()
fmt.Println("door4 is a DoorWithCloserStopper...")
door4.Knob().Turn(); door4.Push()
fmt.Println("door4.Knob().Turn(); door4.Push(); door4.IsOpen() =>", door4.IsOpen())
door4.BeStopperedOn()
fmt.Print("door4.BeStopperedOn(); 0.4 seconds after")
fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
door4.BeStopperedOff()
fmt.Print("door4.BeStopperedOff(); 0.4 seconds after")
fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
door4.Knob().Turn(); door4.Push()
fmt.Println("door4.Knob().Turn(); door4.Push(); door4.IsOpen() =>", door4.IsOpen())
door4.BeStopperedOn()
fmt.Print("door4.BeStopperedOn(); 0.4 seconds after")
fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
door4.Push()
fmt.Print("door4.Push(); 0.4 seconds after")
fmt.Println(", door4.IsOpen() =>", door4.IsOpen())
}