观察者模式
问题
Rust 中如何实现观察者/发布订阅模式?
答案
方式 1:Channel(推荐)
最 Rust 化的方式——用 Channel 实现发布订阅:
use tokio::sync::broadcast;
#[derive(Clone, Debug)]
enum Event {
UserCreated { id: u64, name: String },
UserDeleted { id: u64 },
}
struct EventBus {
sender: broadcast::Sender<Event>,
}
impl EventBus {
fn new(capacity: usize) -> Self {
let (sender, _) = broadcast::channel(capacity);
Self { sender }
}
fn publish(&self, event: Event) {
let _ = self.sender.send(event);
}
fn subscribe(&self) -> broadcast::Receiver<Event> {
self.sender.subscribe()
}
}
#[tokio::main]
async fn main() {
let bus = EventBus::new(100);
// 订阅者 1
let mut rx1 = bus.subscribe();
tokio::spawn(async move {
while let Ok(event) = rx1.recv().await {
println!("订阅者 1: {:?}", event);
}
});
// 订阅者 2
let mut rx2 = bus.subscribe();
tokio::spawn(async move {
while let Ok(event) = rx2.recv().await {
println!("订阅者 2: {:?}", event);
}
});
// 发布事件
bus.publish(Event::UserCreated { id: 1, name: "Alice".into() });
}
方式 2:回调 trait
trait Observer: Send + Sync {
fn on_event(&self, event: &str);
}
struct EventEmitter {
observers: Vec<Box<dyn Observer>>,
}
impl EventEmitter {
fn new() -> Self {
Self { observers: vec![] }
}
fn subscribe(&mut self, observer: Box<dyn Observer>) {
self.observers.push(observer);
}
fn emit(&self, event: &str) {
for observer in &self.observers {
observer.on_event(event);
}
}
}
常见面试问题
Q1: Channel 和回调 trait 方式的区别?
答案:
| 维度 | Channel | 回调 trait |
|---|---|---|
| 线程安全 | 天然安全 | 需要 Send + Sync |
| 解耦度 | 完全解耦 | 需要持有引用 |
| 异步 | 天然异步 | 需要手动处理 |
| 背压 | 有界 channel 自带 | 需手动实现 |
| 推荐场景 | 异步应用 | 简单同步场景 |