深入浅出设计模式-002:观察者模式(Observer Pattern)
一:观察者模式 = 出版者(主题Subject)+订阅者(观察者Observer)
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。
主题和观察者定义了一对多关系。观察者依赖此主题,只要主题状态一有变化,观察者就会被通知。
二:松耦合的威力:当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。
设计原则:为了交互对象之间的松耦合设计而努力。
Subject:这是主题接口,对象使用此接口注册为观察者,或者把自己从观察者中删除。
Observer:所有潜在的观察者必须实现观察者接口,这个接口只有UPDATE一个方法,当主题改变它时被调用。
ConcreteSubject:实现主题接口,还用于在状态改变时更新所有当前观察者。
ConcreteObserver:具体观察者可以是实现此接口的任意类。观察者必须注册具体主题,以便接口更新。
三:观察者定义了对象之间一对多的关系
主题用一个共同的接口来更新观察者
观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者的接口。
使用此模式时,你可从被观察者出推或拉数据
有多个观察者时,不可以依赖特定的通知次序
四:类似于,在网上公布电话,订阅者想订阅时,可以通过电话通知。
public interface Observer{
//当气象观测值改变时,主题会把这些状态值当做方法的参数,传递给观察者
void update(float tmp, float humidity, float pressure);
}
public interface DisplayElement{
//当布告需要显示时,调用此方法
void display();
}
public class CurrentDistionsDisplay : Observer, DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentDistionsDisplay(Subject weatherData){
//注册用
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float tmp, float humidity, float pressure){
temperature = tmp;
this.humidity = humidity;
display();
}
public void display(){
Console.WriteLine("CurrentDistionsDisplay");
}
}
public class StatisticsDisplay : Observer, DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;
public StatisticsDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float tmp, float humidity, float pressure){
temperature = tmp;
this.humidity = humidity;
display();
}
public void display(){
Console.WriteLine("StatisticsDisplay");
}
}
public class ForecastDisplay : Observer, DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;
public ForecastDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float tmp, float humidity, float pressure){
temperature = tmp;
this.humidity = humidity;
display();
}
public void display(){
Console.WriteLine("ForecastDisplay");
}
}
public interface Subject{
//该观察者用来注册或被删除的
void registerObserver(Observer o);
void removeObserver(Observer o);
//当主题状态改变时,这个方法会被调用,以通知所有的观察者
void notifyObservers();
}
public class WeatherData : Subject{
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers = new ArrayList();
}
public void registerObserver(Observer o){
observers.Add(o);
}
public void removeObserver(Observer o){
int index = observers.IndexOf(o);
if(index >= 0)
observers.Remove(index);
}
public void notifyObservers(){
for (int index = 0; index < observers.Count; index++){
Observer observer = (Observer)observers[index];
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged(){
notifyObservers();
}
public void setMeasurements(float temp, float humi, float press){
temperature = temp;
humidity = humi;
pressure = press;
measurementsChanged();
}
}
static void Main(string[] args){
WeatherData weatherData = new WeatherData();
CurrentDistionsDisplay currentDisplay = new CurrentDistionsDisplay(weatherData);
StatisticsDisplay statistics = new StatisticsDisplay(weatherData);
ForecastDisplay forecast = new ForecastDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30);
weatherData.setMeasurements(82, 70, 29);
}