设计模式笔记 - 观察者模式

144 阅读1分钟

观察者模式是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。


解决什么问题?

如果需要对感兴趣的对象进行通知,不感兴趣的对象不需要通知,使用观察者模式很适合。通过维护一个订阅者列表,向特定的对象发送通知。


实现步骤:

  • 定义inotify接口
  • 订阅者实现inotify接口和相关函数
  • 发布者提供订阅、通知等相关接口

优势:

  • 开闭原则。 你无需修改发布者代码就能引入新的订阅者类 。
  • 你可以在运行时建立对象之间的联系。

劣势:

  • 订阅者的通知顺序是随机的。

下面是实现代码:

package main

import "fmt"
import "time"

type notify interface {
	update()
}

type subscriber struct {
	registerId int
	ch         chan struct{}
}

func newSubscriber() *subscriber {
	return &subscriber{
		registerId: -1,
		ch:         make(chan struct{}, 1),
	}
}

func (s *subscriber) setRegisterId(id int) {
	s.registerId = id
}

func (s *subscriber) update() {
	s.ch <- struct{}{}
}

func (s *subscriber) waitNoitify() {
	<-s.ch
	fmt.Printf("subscriber[%d] do something\n", s.registerId)
}

type publisher struct {
	registerId     int
	subscriberList map[int]notify
}

func newPublisher() *publisher {
	return &publisher{
		registerId:     0,
		subscriberList: map[int]notify{},
	}
}

func (p *publisher) subscribe(s notify) int {
	id := p.registerId + 1
	p.registerId = id
	p.subscriberList[id] = s
	fmt.Printf("subscriber[%d] subscribe successfully!!!\n", id)
	return id
}

func (p *publisher) unSubscribe(registerId int) {
	delete(p.subscriberList, registerId)
	fmt.Printf("subscriber[%d] unsubscribe successfully!!!\n", registerId)
}

func (p *publisher) notifySubscribers() {
	for k, v := range p.subscriberList {
		fmt.Printf("publisher inotify subscriber[%d]\n", k)
		v.update()
	}
}

func main() {
	p := newPublisher()
	s1 := newSubscriber()
	s2 := newSubscriber()

	id := p.subscribe(s1)
	s1.setRegisterId(id)

	id = p.subscribe(s2)
	s2.setRegisterId(id)

	go s1.waitNoitify()
	go s2.waitNoitify()

	p.unSubscribe(s1.registerId)

	p.notifySubscribers()

	time.Sleep(time.Second)
}

输出:

subscriber[1] subscribe successfully!!!
subscriber[2] subscribe successfully!!!
subscriber[1] unsubscribe successfully!!!
publisher inotify subscriber[2]
subscriber[2] do something

参考