Golang – 常用设计Observer Pattern

在Go中,可以使用channel和goroutine来实现监听设计

  1. 定义好Observer的Interface
// Observer 定义观察者接口
type Observer interface {
	Update(string)
}

2. 定义好 Subject 对象

// Subject 定义主题对象
type Subject struct {
	observers []Observer // 观察者列表
	mutex     sync.Mutex // 互斥锁,用于保护观察者列表
}

// RegisterObserver 注册观察者
func (s *Subject) RegisterObserver(o Observer) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	s.observers = append(s.observers, o)
}

// DeregisterObserver 注销观察者
func (s *Subject) DeregisterObserver(o Observer) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for i, observer := range s.observers {
		if observer == o {
			s.observers = append(s.observers[:i], s.observers[i+1:]...)
			//s.observers[:i] 举例:0,1,2,3,4 , 使用:x[:2] , 输出: 0,1
			//获取切片顺序N-1之前的
			
			//s.observers[i+1:] 举例:0,1,2,3,4 , 使用:x[3:] , 输出: 3,4
			//获取切片N++之后的
			
			//... 把最后切片分别展开作为输入的参数
			break
		}
	}
}

// NotifyObservers 通知观察者
func (s *Subject) NotifyObservers(msg string) {
	for _, observer := range s.observers {
		observer.Update(msg)
	}
}

3. 定义好 RealObserver

// RealObserver 具体观察者实现
type RealObserver struct {
	id int
}

// Update 更新方法
func (co *RealObserver) Update(msg string) {
	fmt.Printf("观察者 %d 收到消息: %s\n", co.id, msg)
}

4. 使用案例

func main() {
	// 声明需要的主题和真实观察者
	subject := &Subject{}
	observer1 := &RealObserver{id: 1}
	observer2 := &RealObserver{id: 2}

	// 注册观察者
	subject.RegisterObserver(observer1)
	subject.RegisterObserver(observer2)

	// 异步发送通知
	go func() {
		for i := 0; i < 5; i++ {
			subject.NotifyObservers(fmt.Sprintf("消息 %d", i+1))
			time.Sleep(time.Second)
		}
	}()

	// 模拟3秒后注销观察者
	time.Sleep(3 * time.Second)
	subject.DeregisterObserver(observer2)

	time.Sleep(3 * time.Second)
}

显示结果:

观察者 1 收到消息: 消息 1
观察者 2 收到消息: 消息 1
观察者 1 收到消息: 消息 2
观察者 2 收到消息: 消息 2
观察者 1 收到消息: 消息 3
观察者 2 收到消息: 消息 3
观察者 1 收到消息: 消息 4
观察者 1 收到消息: 消息 5

Loading

Facebook评论