观察者模式是一种软件设计模式,它允许对象(通常称为主题)维护一个称为观察者的依赖项列表,并自动通知它们任何状态更改。
许多语言都有这种模式,要么是内置的,要么是在标准库中。
1,首先是Observable,它可以是一个接口,被观察的对象。被观察对象拥有一个观察者列表。
2,Observer,观察者。这也可以是一个接口。
3,ConcreteObservable,保存状态的具体类。如果状态中有任何变化,则调用setState方法,然后调用notify方法反过来通知观察者。
4,ConcreteObserverA/B,处理状态变化的具体观察者。
新建一个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();
}
}
现在建立一个真正的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);
}
执行cargo run,结果如下:
Observer 1 received data: updated_data
Observer 2 received data: updated_data
Observer 1 received data: Again updated data
一个可能的改进是使其线程安全,因为现在这个实现不是线程安全的。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8