观察者模式

观察者模式概念

观察者模式是一种行为设计模式,它允许你定义一种订阅机制,让多个对象监听某一个对象的状态变化。当被监听对象的状态发生变化时,它会自动通知所有订阅了它的对象。

观察者模式的作用

解耦:观察者模式使得观察者和被观察者之间保持松耦合,观察者无需知道被观察者的具体实现细节。

动态交互:可以在运行时动态地添加或删除观察者。

扩展性:易于扩展,新增观察者无需修改被观察者代码。

应用场景

事件处理系统:如GUI系统中,事件源(按钮点击、窗口关闭等)和事件处理程序之间的交互。

发布/订阅系统:如新闻订阅、邮件通知等。

数据绑定:如MVC框架中的视图与模型之间的交互。

Go语言实现观察者模式示例

下面是一个简单的Go语言实现,模拟一个天气预报系统,气象站(被观察者)发布天气变化,多个订阅者(观察者)接收并处理这些信息。

package main

import (
	"fmt"
)

// Observer 接口定义了观察者的行为
type Observer interface {
	Update(temp float64, humidity float64, pressure float64)
}

// Subject 接口定义了被观察者的行为
type Subject interface {
	RegisterObserver(o Observer)
	RemoveObserver(o Observer)
	NotifyObservers()
}

// WeatherData 结构体表示被观察者,即气象站
type WeatherData struct {
	observers   []Observer
	temperature float64
	humidity    float64
	pressure    float64
}

// RegisterObserver 方法用于注册观察者
func (w *WeatherData) RegisterObserver(o Observer) {
	w.observers = append(w.observers, o)
}

// RemoveObserver 方法用于移除观察者
func (w *WeatherData) RemoveObserver(o Observer) {
	for i, observer := range w.observers {
		if observer == o {
			w.observers = append(w.observers[:i], w.observers[i+1:]...)
			break
		}
	}
}

// NotifyObservers 方法用于通知所有观察者
func (w *WeatherData) NotifyObservers() {
	for _, observer := range w.observers {
		observer.Update(w.temperature, w.humidity, w.pressure)
	}
}

// MeasurementsChanged 方法用于当测量值改变时通知观察者
func (w *WeatherData) MeasurementsChanged() {
	w.NotifyObservers()
}

// SetMeasurements 方法用于设置新的测量值
func (w *WeatherData) SetMeasurements(temperature float64, humidity float64, pressure float64) {
	w.temperature = temperature
	w.humidity = humidity
	w.pressure = pressure
	w.MeasurementsChanged()
}

// CurrentConditionsDisplay 结构体表示一个观察者,即当前天气显示
type CurrentConditionsDisplay struct {
	temperature float64
	humidity    float64
	weatherData *WeatherData
}

// Update 方法实现了观察者的行为
func (c *CurrentConditionsDisplay) Update(temp float64, humidity float64, pressure float64) {
	c.temperature = temp
	c.humidity = humidity
	c.display()
}

// display 方法用于显示当前天气信息
func (c *CurrentConditionsDisplay) display() {
	fmt.Printf("Current conditions: %.1fF degrees and %.1f%% humidity\n", c.temperature, c.humidity)
}

func main() {
	// 天气信息
	weatherData := &WeatherData{}
	// 显示天气信息 观察者行为
	currentDisplay := &CurrentConditionsDisplay{weatherData: weatherData}
	// 注册观察者
	weatherData.RegisterObserver(currentDisplay)
	// 天气数据变化
	weatherData.SetMeasurements(80, 65, 30.4)
	weatherData.SetMeasurements(82, 70, 29.2)
	weatherData.SetMeasurements(78, 90, 29.2)
}