定义了对象间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
类似报纸订阅,当订阅报纸后,一有更新就会自动收到,除非退订;这里我们将出版者称为“主题”(Subject),订阅者成为“观察者”(Observer)。
为交互对象之间的松耦合而努力
现在要实现一个气象站,观测三个数据:温度,湿度和气压;气象站有两个布告板:分别显示当前最新值和平均值;当气象数据更新后,气象站要能自动跟新所有布告板。
#!/usr/bin/python class Subject: def register(self, observer): pass def deregister(self, observer): pass def notify_observers(self): pass class Observer: def update(self, temperature, humidity, pressure): pass class DisplayElement: def display(self): pass class WeatherData(Subject): def __init__(self): self.observers = [] def register(self, observer): if observer not in self.observers: self.observers.append(observer) def deregister(self, observer): if observer in self.observers: self.observers.remove(observer) def notify_observers(self): for o in self.observers: o.update(self.temperature, self.humidity, self.pressure) def data_changed(self): self.notify_observers() def set_data(self, temperature, humidity, pressure): self.temperature = temperature self.humidity = humidity self.pressure = pressure self.data_changed() class CurrentDisplay(Observer, DisplayElement): def __init__(self, weather_data=None): self.weather_data = weather_data self.weather_data.register(self) def update(self, temperature, humidity, pressure): self.temperature = temperature self.humidity = humidity self.pressure = pressure self.display() def display(self): print "Current Data: temperature=%s, humidity=%s, pressure=%s" % \ (self.temperature, self.humidity, self.pressure) class AverageDisplay(Observer, DisplayElement): def __init__(self, weather_data=None): self.temperature = [] self.humidity = [] self.pressure = [] self.weather_data = weather_data self.weather_data.register(self) def update(self, temperature, humidity, pressure): self.temperature.append(temperature) self.humidity.append(humidity) self.pressure.append(pressure) self.display() def average(self,lst): n = 0 for x in lst: n += x return n/len(lst) def display(self): print "Average Data: temperature=%s, humidity=%s, pressure=%s" % \ (self.average(self.temperature), \ self.average(self.humidity), \ self.average(self.pressure)) if __name__ == '__main__': weather_data = WeatherData() current = CurrentDisplay(weather_data) average = AverageDisplay(weather_data) weather_data.set_data(18,70,100); print weather_data.set_data(20,70,120); print weather_data.set_data(22,70,80); print weather_data.set_data(24,70,40); print weather_data.deregister(average) weather_data.set_data(30,70,100); print weather_data.set_data(40,70,120); print
Current Data: temperature=18, humidity=70, pressure=100 Average Data: temperature=18, humidity=70, pressure=100 Current Data: temperature=20, humidity=70, pressure=120 Average Data: temperature=19, humidity=70, pressure=110 Current Data: temperature=22, humidity=70, pressure=80 Average Data: temperature=20, humidity=70, pressure=100 Current Data: temperature=24, humidity=70, pressure=40 Average Data: temperature=21, humidity=70, pressure=85 Current Data: temperature=30, humidity=70, pressure=100 Current Data: temperature=40, humidity=70, pressure=120