Rust 中的設計模式:觀察者模式 -Observer-
觀察者模式介紹
觀察者模式是一種軟件設計模式,它允許對象 (通常稱爲主題) 維護一個稱爲觀察者的依賴項列表,並自動通知它們任何狀態更改。
許多語言都有這種模式,要麼是內置的,要麼是在標準庫中。
1,首先是 Observable,它可以是一個接口,被觀察的對象。被觀察對象擁有一個觀察者列表。
2,Observer,觀察者。這也可以是一個接口。
3,ConcreteObservable,保存狀態的具體類。如果狀態中有任何變化,則調用 setState 方法,然後調用 notify 方法反過來通知觀察者。
4,ConcreteObserverA/B,處理狀態變化的具體觀察者。
在 Rust 中實現觀察者模式
新建一個 Rust 項目:
cargo new rust_observer
我們將從 Observer 特徵開始:
trait Observer {
fn update(&self, data:&str);
}
這很簡單,Observer 只有一個方法 update,它有一些數據作爲參數。
現在實現 Subject:
struct Subject<'a> {
observers: Vec<&'a dyn Observer>,
state: String,
}
impl<'a> Subject<'a> {
fn new(state: String) -> Self {
Self {
observers: Vec::new(),
state: state,
}
}
fn attach(&mut self, observer: &'a dyn Observer) {
self.observers.push(observer);
}
fn detach(&mut self, observer: &dyn Observer) {
self.observers.retain(|o| !std::ptr::eq(*o, observer));
}
fn notify(&self) {
for o in &self.observers {
o.update(&self.state);
}
}
fn set_state(&mut self, state: String) {
self.state = state;
self.notify();
}
}
1,在 Subject 結構體中,觀察者必須具有與整個結構體相同的生命週期。
2,new 方法,即構造函數,非常簡單。
3,attach 方法,將觀察者加入列表中。
4,detach 方法,使用指定的閉包進行篩選。閉包返回 true 的每個元素都保留在 vector 中,當它返回 false 時,這些元素被刪除。
5,notify 方法遍歷每個觀察者,並在每個觀察者上調用 update 方法。
6,set_state 方法改變狀態,並調用 notify,以便每個觀察者都能對狀態變化做出反應。
現在建立一個真正的 observer:
struct ConcreteObserver {
name: String,
}
impl Observer for ConcreteObserver {
fn update(&self, data:&str) {
println!("{} received data: {}",self.name,data);
}
}
測試
fn main() {
let mut subject = Subject::new("initial data".to_string());
let observer1=ConcreteObserver {
name: "Observer 1".to_string(),
};
let observer2=ConcreteObserver {
name: "Observer 2".to_string(),
};
subject.attach(&observer1);
subject.attach(&observer2);
subject.set_state("updated_data".to_string());
subject.detach(&observer2);
subject.set_state("Again updated data".to_string());
subject.detach(&observer1);
}
1,我們用一些初始數據實例化 Subject。
2,然後定義兩個觀察者,它們都是 concreteobserver。每一個都有一個不同的名稱。
3,然後我們需要將它們附加到 Subject。
4,set_state 方法被調用,這會將狀態變化發送給兩個觀察者,並將其打印出來。
5,爲了確保 detach 方法正確運行,我們分離第二個觀察者。
6,我們再調用一次 set_state 方法,我們現在應該只得到一條打印語句。
執行 cargo run,結果如下:
Observer 1 received data: updated_data
Observer 2 received data: updated_data
Observer 1 received data: Again updated data
可能的改進
一個可能的改進是使其線程安全,因爲現在這個實現不是線程安全的。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/EsEvWxQo3oi900rx11jvhw