Rust中的设计模式:观察者模式(Observer)

547次阅读  |  发布于11月以前

观察者模式介绍

观察者模式是一种软件设计模式,它允许对象(通常称为主题)维护一个称为观察者的依赖项列表,并自动通知它们任何状态更改。

许多语言都有这种模式,要么是内置的,要么是在标准库中。

1,首先是Observable,它可以是一个接口,被观察的对象。被观察对象拥有一个观察者列表。

2,Observer,观察者。这也可以是一个接口。

3,ConcreteObservable,保存状态的具体类。如果状态中有任何变化,则调用setState方法,然后调用notify方法反过来通知观察者。

4,ConcreteObserverA/B,处理状态变化的具体观察者。

在Rust中实现观察者模式

新建一个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