Observer design pattern is a one-to-many push-notification design, where the object notify all its observing objects when it experiences a change or an event. This is commonly seen in:
The diagram is as follows:
Here is an example in Go. Unlike other languages, Go requires one to create the Communicator structure that acts as the communication abstracts between 2 objects. It itself is a composite patterned structure where it has many subscribers, which is itself. The Communicator structure offers the Subscribe, Unsubscribe, Notify, and Update functions for the event notification and responding purposes.
In MVC, MVVM, or VIPER framework, all 4 event functions above are best known as:
Subscribe ➔ AddEventListenerUnsubscribe ➔ RemoveEventListener / DeleteEventListenerNotify ➔ ActionPerformedUpdate ➔ ActionEventpackage mainimport ( "fmt")/********************************************************************* * INTERFACE - COMMUNICATOR * ********************************************************************/// Communicator structure for managing subscriptions and notificationstype Communicator struct { Label string subscribers []*Communicator action func(interface{})}// New Communicator creates a Communicator objectfunc NewCommunicator(label string) *Communicator { return &Communicator{ Label: label, subscribers: []*Communicator{}, action: nil, }}// Subscribe is for the communicator to add another communicatorfunc (c *Communicator) Subscribe(ch *Communicator) { if ch != nil { fmt.Printf("%v event: %v subbed.\n", c.Label, ch.Label) c.subscribers = append(c.subscribers, ch) }}// Unsubscribe is for the communicator to remove another communicatorfunc (c *Communicator) Unsubscribe(ch *Communicator) { if ch == nil { return } for i, s := range c.subscribers { if s == ch { fmt.Printf("%v event: %v unsubbed.\n", c.Label, s.Label) c.subscribers = append(c.subscribers[:i], c.subscribers[i+1:]...) break } }}// Notify is for the communicator to notify all its subscribers with an// event.func (c *Communicator) Notify(event interface{}) { for _, s := range c.subscribers { s.Update(event) }}// Update runs the executions when the communicator is notifiedfunc (c *Communicator) Update(event interface{}) { if c.action != nil { c.action(event) }}// Register adds an action to the communicator for Update to executefunc (c *Communicator) Register(fx func(interface{})) { c.action = fx}/********************************************************************* * SUBJECT CONCRETE * ********************************************************************/// Subject is the main even trigger. It creates the Channel communicator.type Subject struct { Channel *Communicator}func NewSubject(label string) *Subject { return &Subject{ Channel: NewCommunicator(label), }}func (s *Subject) PressedButton() { fmt.Printf("Subject: user pressed button\n") s.Channel.Notify("Button pressed")}/********************************************************************* * OBSERVER CONCRETE * ********************************************************************/// Observer is the main subscriber to the subject. It has its own// Channel.type Object struct { Channel *Communicator}func NewObject(label string) *Object { o := Object{ Channel: NewCommunicator(label), } o.Channel.action = o.Update return &o}func (o *Object) Update(event interface{}) { fmt.Printf("%v Update: %v\n", o.Channel.Label, event)}/********************************************************************* * MAIN ACTION * ********************************************************************/func main() { s := NewSubject("subject 1") o1 := NewObject("object 1") o2 := NewObject("object 2") // o1 and o2 observes s s.Channel.Subscribe(o1.Channel) s.Channel.Subscribe(o2.Channel) // s received an event s.PressedButton() // o2 stop observing s.Channel.Unsubscribe(o2.Channel) // s received an event s.PressedButton()}// Output:// subject 1 event: object 1 subbed.// subject 1 event: object 2 subbed.// Subject: user pressed button// object 1 Update: Button pressed// object 2 Update: Button pressed// subject 1 event: object 2 unsubbed.// Subject: user pressed button// object 1 Update: Button pressedThat's all about observer design pattern.