You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:09:35