如何在Rust中实现中介者模式?生命周期参数困惑求解
Rust 中介者设计模式实现方案
原代码核心问题
Switcher直接持有SyncMediator的所有权,导致同一个中介者无法被多个同事共享,编译阶段就会报错(mediator被move给switcher1后,后续switcher2、switcher3无法复用同一实例)。SyncMediator的switchers字段持有Switcher的所有权,形成循环所有权依赖,逻辑上无法创建合法实例。sync方法消耗了Switcher和SyncMediator的所有权,调用后对象无法复用,不符合中介者模式的设计意图。
方案一:使用智能指针(Rc)实现灵活双向引用
这是最常用的方案,通过Rc实现共享所有权,RefCell提供内部可变性,完美解决循环引用和所有权冲突问题。
use std::cell::RefCell; use std::rc::Rc; // 前置声明中介者,解决循环类型依赖 struct SyncMediator; // 同事类:开关 struct Switcher { state: bool, // 持有中介者的共享可变引用 mediator: Rc<RefCell<SyncMediator>>, } impl Switcher { fn new(mediator: Rc<RefCell<SyncMediator>>) -> Self { Switcher { state: false, mediator, } } // 通知中介者同步状态 fn sync(&self) { self.mediator.borrow_mut().sync(self.state); } fn get_state(&self) -> bool { self.state } fn set_state(&mut self, value: bool) { self.state = value; } } // 具体中介者:同步所有开关状态 struct SyncMediator { // 持有所有同事的共享可变引用集合 switchers: Vec<Rc<RefCell<Switcher>>>, } impl SyncMediator { fn new() -> Self { SyncMediator { switchers: Vec::new(), } } // 添加同事到中介者管理 fn add(&mut self, switcher: Rc<RefCell<Switcher>>) { self.switchers.push(switcher); } // 同步所有开关到目标状态 fn sync(&mut self, target_state: bool) { for switcher in &self.switchers { switcher.borrow_mut().set_state(target_state); } } } fn main() { // 创建中介者并包装为共享可变引用 let mediator = Rc::new(RefCell::new(SyncMediator::new())); // 创建开关同事,共享同一个中介者 let switcher1 = Rc::new(RefCell::new(Switcher::new(Rc::clone(&mediator)))); let switcher2 = Rc::new(RefCell::new(Switcher::new(Rc::clone(&mediator)))); let switcher3 = Rc::new(RefCell::new(Switcher::new(Rc::clone(&mediator)))); // 将开关添加到中介者管理 mediator.borrow_mut().add(Rc::clone(&switcher1)); mediator.borrow_mut().add(Rc::clone(&switcher2)); mediator.borrow_mut().add(Rc::clone(&switcher3)); // 修改switcher1的状态 switcher1.borrow_mut().set_state(true); let state2 = switcher2.borrow().get_state(); let state3 = switcher3.borrow().get_state(); println!("同步前:switcher2状态 = {state2}, switcher3状态 = {state3}"); // 触发同步 switcher1.borrow().sync(); // 检查同步后的状态 let state2 = switcher2.borrow().get_state(); let state3 = switcher3.borrow().get_state(); println!("同步后:switcher2状态 = {state2}, switcher3状态 = {state3}"); }
方案说明
Rc<RefCell<T>>:Rc让多个Switcher共享同一SyncMediator实例,RefCell允许在共享所有权的前提下修改内部状态(内部可变性)。- 前置声明
SyncMediator:解决Switcher和SyncMediator之间的循环类型依赖。 Rc::clone(&mediator):仅克隆引用计数,而非对象本身,性能开销极低。borrow()/borrow_mut():RefCell提供的方法,用于获取不可变/可变引用,运行时会检查引用规则,避免数据竞争。
方案二:使用生命周期标注的引用(局限性较强)
如果场景简单,不需要动态添加同事或长期共享引用,可以用生命周期绑定的方式,让同事持有中介者的引用,中介者持有同事的所有权。但该方案灵活性差,所有对象的生命周期必须严格一致。
// 中介者结构,绑定生命周期'a struct SyncMediator<'a> { switchers: Vec<&'a mut Switcher<'a>>, } // 同事类:开关,绑定生命周期'a struct Switcher<'a> { state: bool, mediator: &'a SyncMediator<'a>, } impl<'a> Switcher<'a> { fn new(mediator: &'a SyncMediator<'a>) -> Self { Switcher { state: false, mediator, } } fn get_state(&self) -> bool { self.state } fn set_state(&mut self, value: bool) { self.state = value; } } impl<'a> SyncMediator<'a> { fn new() -> Self { SyncMediator { switchers: Vec::new(), } } fn add(&mut self, switcher: &'a mut Switcher<'a>) { self.switchers.push(switcher); } fn sync(&mut self, target_state: bool) { for switcher in &mut self.switchers { switcher.set_state(target_state); } } } fn main() { let mut mediator = SyncMediator::new(); let mut switcher1 = Switcher::new(&mediator); let mut switcher2 = Switcher::new(&mediator); let mut switcher3 = Switcher::new(&mediator); mediator.add(&mut switcher1); mediator.add(&mut switcher2); mediator.add(&mut switcher3); switcher1.set_state(true); let state2 = switcher2.get_state(); let state3 = switcher3.get_state(); println!("同步前:switcher2状态 = {state2}, switcher3状态 = {state3}"); mediator.sync(switcher1.get_state()); let state2 = switcher2.get_state(); let state3 = switcher3.get_state(); println!("同步后:switcher2状态 = {state2}, switcher3状态 = {state3}"); }
方案说明
- 生命周期
'a绑定了Switcher和SyncMediator的生命周期,确保Switcher持有的中介者引用始终有效。 - 中介者持有同事的可变引用,添加同事后无法单独修改同事状态(除非通过中介者),否则会触发可变引用冲突。
- 无法在运行时动态创建新同事并添加到中介者,仅适合固定数量同事的简单场景。
内容的提问来源于stack exchange,提问作者Fedor Obraztsov
相关产品推荐
相关产品推荐

