前言 觀察者模式(Observer Pattern)是一種行為型設計模式,它定義了一種一對多的依賴關係,當一個對象的狀態發生改變時,其所有依賴者都會收到通知並自動更新。 在觀察者模式中,有兩種主要的角色: 觀察者(Observer):觀察者是一個介面或抽象類,它定義了一個更新的介面,使得被觀察者在狀 ...
前言
觀察者模式(Observer Pattern)是一種行為型設計模式,它定義了一種一對多的依賴關係,當一個對象的狀態發生改變時,其所有依賴者都會收到通知並自動更新。
在觀察者模式中,有兩種主要的角色:
- 觀察者(Observer):觀察者是一個介面或抽象類,它定義了一個更新的介面,使得被觀察者在狀態發生變化時可以通知觀察者進行更新操作。
- 被觀察者(Subject):被觀察者是一個類,它維護了一組觀察者對象,並提供了添加、刪除和通知觀察者的方法。當被觀察者的狀態發生變化時,它會通知所有的觀察者進行更新操作。
被觀察者對象在狀態或內容(數據)發生變化時,會通知所有觀察者對象,使它們能夠做出相應的變化(如自動更新自己的信息)。
工作原理
- 觀察者通過訂閱被觀察者,註冊自己到被觀察者的觀察者列表中。
- 被觀察者維護了一個觀察者列表,當自身狀態發生變化時,遍歷觀察者列表,調用每個觀察者的更新方法。
- 觀察者收到通知後,執行相應的更新操作,通常是從被觀察者獲取最新的狀態信息,併進行相應的處理。
優點
- 解耦性: 觀察者模式將觀察者和被觀察者解耦,使得它們可以獨立地變化和復用。
- 可擴展性: 可以根據需要動態地增加和刪除觀察者,從而實現系統的靈活性和可擴展性。
- 通知機制: 觀察者模式提供了一種簡單的通知機制,使得被觀察者可以在狀態發生變化時通知所有的觀察者。
缺點
- 可能引起迴圈依賴: 如果觀察者和被觀察者之間存在雙向依賴關係,可能會導致迴圈依賴的問題。這樣會使系統變得複雜,難以維護和理解。
- 通知順序不確定: 觀察者模式中觀察者的通知順序通常是不確定的,這可能會導致一些問題,特別是在多個觀察者對同一事件進行響應時。
- 可能導致性能問題: 如果被觀察者對象頻繁地改變狀態,會導致大量的通知操作,可能會影響系統的性能。
- 可能引發併發問題: 如果在多線程環境下使用觀察者模式,可能會引發併發問題,需要額外的同步措施來保證線程安全。
- 過多的細粒度對象: 觀察者模式可能會導致系統中存在大量的細粒度的觀察者對象,這可能會增加系統的複雜性和記憶體消耗。
示例代碼
Go
代碼文件: observer/observer.go
package observer
import "fmt"
// 觀察者介面
type Observer interface {
Update(myapp MyAPP)
}
// 被觀察者
type MyAPP struct {
observers []Observer
serverity int
}
func (m *MyAPP) GetServerity() int {
return m.serverity
}
func (m *MyAPP) SetServerity(s int) {
if s < 0 || s > 3 {
fmt.Println("serverity must be an integer between 0 and 3")
return
}
m.serverity = s
fmt.Printf("Current severity is %d.\n", m.serverity)
m.notify()
}
func (m *MyAPP) notify() {
for _, observer := range m.observers {
observer.Update(*m)
}
}
func (m *MyAPP) AddObserver(observer Observer) {
m.observers = append(m.observers, observer)
}
type Employee struct{}
func (e *Employee) Update(myapp MyAPP) {
if myapp.GetServerity() == 1 {
fmt.Println("Employee: I'm notified!")
}
}
type Manager struct{}
func (m *Manager) Update(myapp MyAPP) {
if myapp.GetServerity() == 2 {
fmt.Println("Manager: I'm notified!")
}
}
type Director struct{}
func (d *Director) Update(myapp MyAPP) {
if myapp.GetServerity() == 3 {
fmt.Println("Director: I'm notified!")
}
}
代碼文件: main.go
package main
import (
"design-pattern-go/observer"
)
func main() {
myapp := &observer.MyAPP{}
employee := &observer.Employee{}
manager := &observer.Manager{}
director := &observer.Director{}
myapp.AddObserver(employee)
myapp.AddObserver(manager)
myapp.AddObserver(director)
myapp.SetServerity(0)
myapp.SetServerity(1)
myapp.SetServerity(2)
myapp.SetServerity(3)
myapp.SetServerity(4)
}
運行結果
$ go run main.go
Current severity is 0.
Current severity is 1.
Employee: I'm notified!
Current severity is 2.
Manager: I'm notified!
Current severity is 3.
Director: I'm notified!
serverity must be an integer between 0 and 3
Python
from abc import ABCMeta, abstractmethod
class MyApp:
"""被觀察者"""
def __init__(self):
self.__observers = []
self.__severity = 0
def get_severity(self):
return self.__severity
def set_severity(self, severity: int):
if not isinstance(severity, int) or severity < 0 or severity > 3:
raise ValueError("severity must be an integer between 0 and 3")
self.__severity = severity
print(f"current severity: {severity}")
self.notify()
def add_observer(self, observer):
self.__observers.append(observer)
def notify(self):
"""遍歷觀察者列表, 調用每個觀察者的update方法"""
for o in self.__observers:
o.update(self)
class Observer(metaclass=ABCMeta):
"""觀察者基類"""
@abstractmethod
def update(self, myapp: MyApp):
pass
class Employee(Observer):
def update(self, myapp: MyApp):
if myapp.get_severity() == 1:
print("An employee is notified")
class Manager(Observer):
def update(self, myapp: MyApp):
if myapp.get_severity() == 2:
print("A manager is notified")
class Director(Observer):
def update(self, myapp: MyApp):
if myapp.get_severity() == 3:
print("A director is notified")
if __name__ == "__main__":
myapp = MyApp()
employee = Employee()
manager = Manager()
director = Director()
myapp.add_observer(employee)
myapp.add_observer(manager)
myapp.add_observer(director)
myapp.set_severity(1)
myapp.set_severity(2)
myapp.set_severity(3)
運行結果:
$ python .\observer.py
current severity: 1
An employee is notified
current severity: 2
A manager is notified
current severity: 3
A director is notified
本文來自博客園,作者:花酒鋤作田,轉載請註明原文鏈接:https://www.cnblogs.com/XY-Heruo/p/18225460