廢了這些年的程序員,必須掌握一些設計模式才算是真正稱得上是“老司機”了。今天要介紹的就是其中之一——觀察者模式。
1. 認識觀察者模式
先說說這個模式的背景,這個模式主要是用于一對多的情況下,當一個對象發(fā)生改變時,所有其它對象都會受到通知并進行相應的操作。這樣看起來觀察者模式似乎很簡單,但實現(xiàn)起來也有些講究。
在觀察者模式中,有兩個角色需要我們關注下。一個是被觀察者,我們叫它主題(Subject),即被觀察的對象。它有一些狀態(tài)需要在狀態(tài)變化時通知其它對象加以處理。另一個是觀察者(Observer),接收傳入的信息并進行處理。當然,觀察者也有多種形式,可以是類、函數(shù)、接口等。如果觀察者僅僅只有一種,那就是傻觀察者了。
對于被觀察者和觀察者,我們一定要用接口和抽象類進行定義:主題應該有一個添加觀察者、刪除觀察者、以及通知所有觀察者的方法。而觀察者則需要有一個update方法來接收主題通知時傳遞過來的信息。這里帶來一段偽代碼。
```python
# 主題接口,記得從ABC繼承
class Subject(metaclass=ABCMeta):
def registerObserver(self, observer): pass
def removeObserver(self, observer): pass
def notifyObserver(self): pass
# 觀察者接口,從ABC繼承
class Observer(metaclass=ABCMeta):
def update(self, temp, humidity, pressure): pass
```
這樣我們可以定義觀察者的接口和被觀察者的接口了。接著我們就可以進行下一步——實現(xiàn)主題和觀察者的類了。
2. 實現(xiàn)觀察者模式
眾所周知,Python中的面向對象編程是一種“急功近利”的做法。好在面向對象語言中多態(tài)的概念可以讓這個模式的實現(xiàn)變得更加簡單?,F(xiàn)在假設我們要建立一個氣象站,并提供給用戶當前的溫度、濕度和氣壓的變化信息。首先我們需要實現(xiàn)主題類WeatherData。下面是該類的簡單實現(xiàn):
```python
class WeatherData(Subject):
def __init__(self):
self.observers = []
self.temperature = None
self.humidity = None
self.pressure = None
def registerObserver(self, observer):
self.observers.append(observer)
def removeObserver(self, observer):
self.observers.remove(observer)
def notifyObserver(self):
for observer in self.observers:
observer.update(self.temperature, self.humidity, self.pressure)
def measurementsChanged(self):
self.notifyObserver()
def setMeasurements(self, temperature, humidity, pressure):
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
self.measurementsChanged()
```
實現(xiàn)了主題類之后,我們可以實現(xiàn)觀察者類了。這里,我們以展示當前氣象情況的類CurrentConditionsDisplay為例。下面是該類的代碼:
```python
class CurrentConditionsDisplay(Observer):
def __init__(self, weather):
self.temperature = None
self.humidity = None
self.pressure = None
self.weather = weather
self.weather.registerObserver(self)
def update(self, temperature, humidity, pressure):
self.temperature = temperature
self.humidity = humidity
self.pressure = pressure
self.display()
def display(self):
print("Current conditions: %.1fF degrees and %.1f%% humidity" % (self.temperature, self.humidity))
```
這樣我們就可以實現(xiàn)一個簡單的觀察者模式了!下面展示一下模型如何使用:
```python
weatherStation = WeatherData()
currentDisplay = CurrentConditionsDisplay(weatherStation)
weatherStation.setMeasurements(80, 65, 30.4)
weatherStation.setMeasurements(82, 70, 29.2)
weatherStation.setMeasurements(78, 90, 29.2)
```
3. 如何有親和性地使用觀察者模式
觀察者模式最大的問題可能在于如果被觀察者和觀察者之間有太多的交互,那么這個模式可能會導致程序的難以維護。解決這個問題的一個辦法是使用消息隊列,將主題和所有的觀察者分開,并且異步地傳遞消息。
現(xiàn)在讓我們來舉一個實際的例子,有一個購物車,里面有多個商品,用戶可以隨時刪除這些商品。我們需要在商品被刪除后通知相應的觀察者。下面是一段示例的Python代碼:
```python
from queue import Queue, Empty
class ShoppingCart:
def __init__(self):
self.items = []
self.observers = Queue()
def __add__(self, item):
self.items.append(item)
return self
def __iter__(self):
return iter(self.items)
def __delitem__(self, index):
del self.items[index]
self.notifyAll()
def registerObserver(self, observer):
self.observers.put(observer)
def removeObserver(self, observer):
try:
while True:
a = self.observers.get_nowait()
self.observers.put(a)
if a != observer:
self.observers.get_nowait()
except Empty:
return
def notifyAll(self):
while not self.observers.empty():
observer = self.observers.get_nowait()
observer() // 別忘了這是一個“傻觀察者”!
```
上述代碼中,我們將購物車和觀察者進行了分離,并將通知消息異步發(fā)送給觀察者。這樣我們就大大簡化了程序的實現(xiàn),最終得到了一個適合維護的代碼結構。
4. 結語:在實現(xiàn)觀察者模式的過程中,我們需要考慮到兩個關鍵部分:被觀察者以及觀察者的接口。同時,為了維護程序的可讀性和可維護性,我們應該對它們分別定義一個接口或抽象類。如果這樣做的話,就可以使我們的代碼邏輯更加清晰,同時我們將更容易地對其進行測試。同時,我們還提供了針對觀察者模式的優(yōu)化技巧,通過使用消息隊列等先進技術,可以更擁有更高的程序效率??傊?,觀察者模式提供了一種將代碼進行結構化的方式,將帶給你開發(fā)優(yōu)秀產(chǎn)品的不錯選擇! www.yinyiprinting.cn 寧波海美seo網(wǎng)絡優(yōu)化公司 是網(wǎng)頁設計制作,網(wǎng)站優(yōu)化,企業(yè)關鍵詞排名,網(wǎng)絡營銷知識和開發(fā)愛好者的一站式目的地,提供豐富的信息、資源和工具來幫助用戶創(chuàng)建令人驚嘆的實用網(wǎng)站。 該平臺致力于提供實用、相關和最新的內(nèi)容,這使其成為初學者和經(jīng)驗豐富的專業(yè)人士的寶貴資源。
聲明本文內(nèi)容來自網(wǎng)絡,若涉及侵權,請聯(lián)系我們刪除! 投稿需知:請以word形式發(fā)送至郵箱18067275213@163.com
站長大神好久不跟新了。認真拜讀。