Summer SALE

Rust 观察者模式讲解和代码示例

观察者是一种行为设计模式 允许一个对象将其状态的改变通知其他对象

观察者模式提供了一种作用于任何实现了订阅者接口的对象的机制 可对其事件进行订阅和取消订阅

Conceptual example

In Rust, a convenient way to define a subscriber is to have a function as a callable object with complex logic passing it to a event publisher.

In this Observer example, Subscribers are either a lambda function or an explicit function subscribed to the event. Explicit function objects could be also unsubscribed (although, there could be limitations for some function types).

use crate::observer::{Event, Publisher};

/// Editor has its own logic and it utilizes a publisher
/// to operate with subscribers and events.
pub struct Editor {
    publisher: Publisher,
    file_path: String,

impl Editor {
    pub fn events(&mut self) -> &mut Publisher {
        &mut self.publisher

    pub fn load(&mut self, path: String) {
        self.file_path = path.clone();
        self.publisher.notify(Event::Load, path);

    pub fn save(&self) {
        self.publisher.notify(Event::Save, self.file_path.clone());

use std::collections::HashMap;

/// An event type.
#[derive(PartialEq, Eq, Hash, Clone)]
pub enum Event {

/// A subscriber (listener) has type of a callable function.
pub type Subscriber = fn(file_path: String);

/// Publisher sends events to subscribers (listeners).
pub struct Publisher {
    events: HashMap<Event, Vec<Subscriber>>,

impl Publisher {
    pub fn subscribe(&mut self, event_type: Event, listener: Subscriber) {;;

    pub fn unsubscribe(&mut self, event_type: Event, listener: Subscriber) {
            .retain(|&x| x != listener);

    pub fn notify(&self, event_type: Event, file_path: String) {
        let listeners =;
        for listener in listeners {

use editor::Editor;
use observer::Event;

mod editor;
mod observer;

fn main() {
    let mut editor = Editor::default();, |file_path| {
        let log = "/path/to/log/file.txt".to_string();
        println!("Save log to {}: Load file {}", log, file_path);
    });, save_listener);

    editor.load("test2.txt".into());;, save_listener);;

fn save_listener(file_path: String) {
    let email = "".to_string();
    println!("Email to {}: Save file {}", email, file_path);


Save log to /path/to/log/file.txt: Load file test1.txt
Save log to /path/to/log/file.txt: Load file test2.txt
Email to Save file test2.txt


C# 观察者模式讲解和代码示例 C++ 观察者模式讲解和代码示例 Go 观察者模式讲解和代码示例 Java 观察者模式讲解和代码示例 PHP 观察者模式讲解和代码示例 Python 观察者模式讲解和代码示例 Ruby 观察者模式讲解和代码示例 Swift 观察者模式讲解和代码示例 TypeScript 观察者模式讲解和代码示例