package main import ( "errors" ) ////// // Interfaces. ////// // Subject actions definition. type ISubject interface { // Attach an Observer to observe the subject. Attach(o Observer) (bool, error) // Detach an Observer which is observing the subject. Detach(o Observer) (bool, error) // Notify observers of a change. // // NOTE: This is why it's pattern from the behavioral category. Notify() (bool, error) } ////// // Object definition. ////// type Subject struct { // Could be anything. For flexibility, could be an `interface{}`. // It would require type casting. ready bool // List of observers. observers []Observer } ////// // ISubject implementation. ////// // Attach an observer to observe the subject. func (s *Subject) Attach(o Observer) (bool, error) { for _, observer := range s.observers { if observer == o { return false, errors.New("Observer already exists") } } s.observers = append(s.observers, o) return true, nil } // Detach an observer which is observing the subject. func (s *Subject) Detach(o Observer) (bool, error) { for i, observer := range s.observers { if observer == o { s.observers = append(s.observers[:i], s.observers[i+1:]...) return true, nil } } return false, errors.New("Observer not found") } // Notify observers of a change. func (s *Subject) Notify() (bool, error) { for _, observer := range s.observers { observer.Do(s.ready) } return true, nil } ////// // Accessors. ////// // SetReadiness update readiness. func (s *Subject) SetReadiness(ready bool) { s.ready = ready // Notifies all observers of the change. s.Notify() } ////// // Factory. ////// // NewSubject creates a new subject. func NewSubject(ready bool) Subject { return Subject{ ready: ready, } }