设计模式之观察者模式

 什么是观察者模式

它定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知。

设计原则

为了交互对象之间的松藕合设计而努力:松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。

图解观察者模式

一个新的对象需要订阅:当有一个新的需要订阅的对象时,需要先向主题对象调用注册接口注册订阅信息。

 

 新的订阅者:有了新的订阅者后,主题对象将向订阅者4也推送订阅消息 。

数据更新:一旦数据有更新,将向所有订阅者更新信息 。

有订阅者需要离开:有订阅者需要离开时,将该订阅者在订阅者列表中移除。

离开后:不再向离开的订阅者推送消息。

例子

现在有一个气象站和布告站(湿度,温度,气压),WeatherData对象(获取气象站数据,更新布告站),我们的工作就是建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况,气象统计和天气预报。

定义观察者模式:类图

 

 

 

 设计气象站

实现气象站

主题接口:

public interface Subject
{
void registerObserver(Observer o);//注册
void removeObserver(Observer o);//删除
void notifyObservers();//改变状态通知
}

观察者接口:

public interface Observer
{
/// <summary>
/// 当气象观察者改变时,主题把这些状态值当作方法参数,传送给观察者。所有观察者都是实现此方法。
/// </summary>
void update(float temp, float humidity, float pressure);
}

显示接口(非必需):

public interface DisplayElement
{
void display();//当布告栏需要显示时,调用此方法
}

主题对象:

public class WeatherData : Subject//实现主题接口
{
private List<Observer> observers;//用来记录观察者
private float temperature;
private float humidity;
private float pressure;
public WeatherData()
{
observers = new List<Observer>();
}
public void registerObserver(Observer o)//注册观察者时,添加
{
observers.Add(o);
}
public void removeObserver(Observer o)//注销观察者时,删除
{
observers.Remove(o);
}
public void notifyObservers()//把消息通知所有观察者,因为它们都实现了update
{
foreach (Observer Observer in observers)
{
Observer.update(temperature, humidity, pressure);
}
}
public void measurementChanged()//更新数据,通知观察者
{
notifyObservers();
}
public void setMeasurements(float temp, float humidity, float pressure)
{
this.temperature = temp;
this.humidity = humidity;
this.pressure = pressure;
measurementChanged();
}

}

观察者对象:

public class CurrentConditionsDisplay : Observer, DisplayElement//实现观察者接口和显示接口
{
private float temperature;
private float humidity;
private Subject weatherDate;
public CurrentConditionsDisplay(Subject weatherDate)
{
this.weatherDate = weatherDate;
weatherDate.registerObserver(this);//在构造方法中注册(订阅)
}
public void display()
{
Console.WriteLine($"temperature:{temperature},humidity:{humidity}");
}
public void update(float temp, float humidity, float pressure)//当此方法被调用时,更新温度和湿度并显示
{
this.temperature = temp;
this.humidity = humidity;
display();
}
}

测试:

 

static void Main(string[] args)
{
WeatherData weatherData = new WeatherData();//建立一个主题对象
CurrentConditionsDisplay currentConditions = new CurrentConditionsDisplay(weatherData);//注册(订阅)
//模拟数据
weatherData.setMeasurements(80, 54, 34);
weatherData.setMeasurements(1, 2, 3);
weatherData.setMeasurements(12, 23, 34);
Console.ReadKey();
}

运行结果:

 

posted on 2018-01-04 14:55  Mr.Tan&  阅读(1041)  评论(2编辑  收藏  举报

导航