GoLang design pattern 13 - observer pattern

Observer pattern is a behavioral design pattern. This pattern allows one instance (which can be called a target object) ...

Observer pattern is a behavioral design pattern. This pattern allows one instance (which can be called a target object) to publish various events to other instances (observers). These observers subscribe to the target object so that they receive event notifications whenever the target object changes.

Let's take a look at an example: various goods are often out of stock on e-commerce websites. If customers are already paying attention to these goods, the out of stock of these goods will have a bad experience for them. If customers still want to buy these products, there are usually the following solutions:

  1. Customers check whether these goods are on sale at a certain frequency
  2. The e-commerce platform regularly pushes all commodity information on the shelves to users
  3. Customers only subscribe to the information of specific products they are concerned about, and they will be notified when these products are on the shelves again; Multiple customers can subscribe to the information of the same product

Option 3 is the most feasible option. This is what the observer model can do. The core components of observer mode are:

  • Subject  : The target object is an instance that publishes related events when changes occur
  • Observer  : Observers, who subscribe to the information of the target object, will receive notifications of some specific events

Usually, Subject and Observer are defined as interfaces, and the real use is their specific implementation.

UML class diagram is as follows:

  Here is an example code:

observer.go:

type observer interface { update(string) getID() string }

subject.go:

type subject interface { register(Observer observer) deregister(Observer observer) notifyAll() }

item.go:

import "fmt" type item struct { observerList []observer name string inStock bool } func newItem(name string) *item { return &item{ name: name, } } func (i *item) updateAvailability() { fmt.Printf("Item %s is now in stock\n", i.name) i.inStock = true i.notifyAll() } func (i *item) register(o observer) { i.observerList = append(i.observerList, o) } func (i *item) deregister(o observer) { i.observerList = removeFromSlice(i.observerList, o) } func (i *item) notifyAll() { for _, observer := range i.observerList { observer.update(i.name) } } func removeFromSlice(observerList []observer, observerToRemove observer) []observer { observerListLength := len(observerList) for i, observer := range observerList { if observerToRemove.getID() == observer.getID() { observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1] return observerList[:observerListLength-1] } } return observerList }

customer.go:

import "fmt" type customer struct { id string } func (c *customer) update(itemName string) { fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName) } func (c *customer) getID() string { return c.id }

In the above code, item is the implementation of subject and customer is the implementation of observer.

Look at the next scene class main.go:

func main() { shirtItem := newItem("GoLang Design Patterns") observerFirst := &customer observerSecond := &customer shirtItem.register(observerFirst) shirtItem.register(observerSecond) shirtItem.updateAvailability() }

After execution, the output contents are:

Item GoLang Design Patterns is now in stock Sending email to customer [email protected] for item GoLang Design Patterns Sending email to customer [email protected] for item GoLang Design Patterns

Code uploaded to GitHub:   zhyea / go-patterns / observer-pattern

END!

7 November 2021, 17:40 | Views: 7481

Add new comment

For adding a comment, please log in
or create account

0 comments