观察者模式(Observer Pattern)定义了一种一对多的依赖关系,当被观察者(Subject)的状态发生变化时,它将会通知观察者们(Observers)进行某种操作。

例如我们希望定义温度计和压力计,在天气信息发生变化时自动更新,而非自己反复的查询是否天气信息有发生变化。这里天气信息就是被观察者,而温度计和压力计就是观察者。

#代码示例

#观察者及被观察者接口

被观察者
1
2
3
4
5
6
public interface ISubject
{
void RegisterObserver(IObserver observer);
void UnregisterObserver(IObserver observer);
void NotifyObservers();
}
观察者
1
2
3
4
public interface IObserver
{
void Update(ISubject subject);
}

#观察者实现

温度计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TemperatureObserver : IObserver
{
private ISubject subject;
public TemperatureObserver(ISubject subject)
{
this.subject = subject;
this.subject.RegisterObserver(this);
}

public void Update(ISubject subject)
{
WeatherData weatherData = subject as WeatherData;

//注意这里我们是从主动从被观察者那里去获取数据
if (weatherData != null)
Console.WriteLine("Temperature is " + weatherData.Temperature);
}
}
压力计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PressureObserver : IObserver
{
private ISubject subject;
public PressureObserver(ISubject subject)
{
this.subject = subject;
this.subject.RegisterObserver(this);
}

public void Update(ISubject subject)
{
WeatherData weatherData = subject as WeatherData;
if (weatherData != null)
Console.WriteLine("Pressure is " + weatherData.Pressure);
}
}

#被观察者实现

天气数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class WeatherData : ISubject
{
private List<IObserver> observersList;

public float Temperature { get; private set; }
public float Humidity { get; private set; }
public float Pressure { get; private set; }

public WeatherData()
{
observersList = new List<IObserver>();
}

public void NotifyObservers()
{
observersList.ForEach(o => o.Update(this));
}

public void RegisterObserver(IObserver o)
{
observersList.Add(o);
}

public void UnregisterObserver(IObserver o)
{
observersList.Remove(o);
}

private void measurementsChanged()
{
NotifyObservers();
}

public void SetMeasurements(float temperature, float humidity, float pressure)
{
this.Temperature = temperature;
this.Humidity = humidity;
this.Pressure = pressure;
measurementsChanged();
}
}

#测试及结果

测试代码
1
2
3
4
5
6
7
8
WeatherData weatherData = new WeatherData();
TemperatureObserver temperatureObserver = new TemperatureObserver(weatherData);
PressureObserver pressureObserver = new PressureObserver(weatherData);

weatherData.SetMeasurements(30, 20, 10);
weatherData.SetMeasurements(20, 40, 5);
weatherData.UnregisterObserver(temperatureObserver);
weatherData.SetMeasurements(10, 50, 15);

运行结果:

观察者模式运行结果