跳到主要内容

观察者模式

问题

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 自带需手动实现
推荐场景异步应用简单同步场景

相关链接