廢了這些年的程序員,必須掌握一些設(shè)計(jì)模式才算是真正稱得上是“老司機(jī)”了。今天要介紹的就是其中之一——觀察者模式。
1. 認(rèn)識(shí)觀察者模式
先說說這個(gè)模式的背景,這個(gè)模式主要是用于一對(duì)多的情況下,當(dāng)一個(gè)對(duì)象發(fā)生改變時(shí),所有其它對(duì)象都會(huì)受到通知并進(jìn)行相應(yīng)的操作。這樣看起來觀察者模式似乎很簡(jiǎn)單,但實(shí)現(xiàn)起來也有些講究。
在觀察者模式中,有兩個(gè)角色需要我們關(guān)注下。一個(gè)是被觀察者,我們叫它主題(Subject),即被觀察的對(duì)象。它有一些狀態(tài)需要在狀態(tài)變化時(shí)通知其它對(duì)象加以處理。另一個(gè)是觀察者(Observer),接收傳入的信息并進(jìn)行處理。當(dāng)然,觀察者也有多種形式,可以是類、函數(shù)、接口等。如果觀察者僅僅只有一種,那就是傻觀察者了。
對(duì)于被觀察者和觀察者,我們一定要用接口和抽象類進(jìn)行定義:主題應(yīng)該有一個(gè)添加觀察者、刪除觀察者、以及通知所有觀察者的方法。而觀察者則需要有一個(gè)update方法來接收主題通知時(shí)傳遞過來的信息。這里帶來一段偽代碼。
```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
```
這樣我們可以定義觀察者的接口和被觀察者的接口了。接著我們就可以進(jìn)行下一步——實(shí)現(xiàn)主題和觀察者的類了。
2. 實(shí)現(xiàn)觀察者模式
眾所周知,Python中的面向?qū)ο缶幊淌且环N“急功近利”的做法。好在面向?qū)ο笳Z(yǔ)言中多態(tài)的概念可以讓這個(gè)模式的實(shí)現(xiàn)變得更加簡(jiǎn)單?,F(xiàn)在假設(shè)我們要建立一個(gè)氣象站,并提供給用戶當(dāng)前的溫度、濕度和氣壓的變化信息。首先我們需要實(shí)現(xiàn)主題類WeatherData。下面是該類的簡(jiǎn)單實(shí)現(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()
```
實(shí)現(xiàn)了主題類之后,我們可以實(shí)現(xiàn)觀察者類了。這里,我們以展示當(dāng)前氣象情況的類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))
```
這樣我們就可以實(shí)現(xiàn)一個(gè)簡(jiǎ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. 如何有親和性地使用觀察者模式
觀察者模式最大的問題可能在于如果被觀察者和觀察者之間有太多的交互,那么這個(gè)模式可能會(huì)導(dǎo)致程序的難以維護(hù)。解決這個(gè)問題的一個(gè)辦法是使用消息隊(duì)列,將主題和所有的觀察者分開,并且異步地傳遞消息。
現(xiàn)在讓我們來舉一個(gè)實(shí)際的例子,有一個(gè)購(gòu)物車,里面有多個(gè)商品,用戶可以隨時(shí)刪除這些商品。我們需要在商品被刪除后通知相應(yīng)的觀察者。下面是一段示例的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() // 別忘了這是一個(gè)“傻觀察者”!
```
上述代碼中,我們將購(gòu)物車和觀察者進(jìn)行了分離,并將通知消息異步發(fā)送給觀察者。這樣我們就大大簡(jiǎn)化了程序的實(shí)現(xiàn),最終得到了一個(gè)適合維護(hù)的代碼結(jié)構(gòu)。
4. 結(jié)語(yǔ):在實(shí)現(xiàn)觀察者模式的過程中,我們需要考慮到兩個(gè)關(guān)鍵部分:被觀察者以及觀察者的接口。同時(shí),為了維護(hù)程序的可讀性和可維護(hù)性,我們應(yīng)該對(duì)它們分別定義一個(gè)接口或抽象類。如果這樣做的話,就可以使我們的代碼邏輯更加清晰,同時(shí)我們將更容易地對(duì)其進(jìn)行測(cè)試。同時(shí),我們還提供了針對(duì)觀察者模式的優(yōu)化技巧,通過使用消息隊(duì)列等先進(jìn)技術(shù),可以更擁有更高的程序效率??傊?,觀察者模式提供了一種將代碼進(jìn)行結(jié)構(gòu)化的方式,將帶給你開發(fā)優(yōu)秀產(chǎn)品的不錯(cuò)選擇! yinyiprinting.cn 寧波海美seo網(wǎng)絡(luò)優(yōu)化公司 是網(wǎng)頁(yè)設(shè)計(jì)制作,網(wǎng)站優(yōu)化,企業(yè)關(guān)鍵詞排名,網(wǎng)絡(luò)營(yíng)銷知識(shí)和開發(fā)愛好者的一站式目的地,提供豐富的信息、資源和工具來幫助用戶創(chuàng)建令人驚嘆的實(shí)用網(wǎng)站。 該平臺(tái)致力于提供實(shí)用、相關(guān)和最新的內(nèi)容,這使其成為初學(xué)者和經(jīng)驗(yàn)豐富的專業(yè)人士的寶貴資源。
聲明本文內(nèi)容來自網(wǎng)絡(luò),若涉及侵權(quán),請(qǐng)聯(lián)系我們刪除! 投稿需知:請(qǐng)以word形式發(fā)送至郵箱[email protected]
站長(zhǎng)大神好久不跟新了。認(rèn)真拜讀。