#pattern #stream #rust-patterns #async

mediator

Rust中中介者模式的实现

6个版本

0.2.2 2022年4月25日
0.2.1 2022年4月24日
0.2.0 2022年3月27日
0.1.2 2022年3月18日

#872 in 异步

MIT 许可协议

125KB
3K SLoC

mediator-rs

https://github.com/Neo-Ciber94/mediator-rs/blob/main/LICENSE https://docs.rs/mediator/latest/mediator/ https://crates.io/crates/mediator https://github.com/Neo-Ciber94/mediator-rs/actions/workflows/ci.yml

受C# MediatR 启发的Rust中中介者模式的实现。

中介者模式

https://en.wikipedia.org/wiki/Mediator_pattern

使用方法

[dependencies]
mediator = "0.2"

测试

运行测试使用以下命令

cargo test --all-features

示例

基本用法

use mediator::{DefaultMediator, Mediator, Request, Event, RequestHandler, EventHandler};

#[derive(Clone, Debug)]
enum Op {
 Add(f32, f32),
 Sub(f32, f32),
 Mul(f32, f32),
 Div(f32, f32),
}

struct MathRequest(Op);
impl Request<Option<f32>> for MathRequest {}

#[derive(Clone, Debug)]
struct MathEvent(Op, Option<f32>);
impl Event for MathEvent {}

struct MathRequestHandler(DefaultMediator);
impl RequestHandler<MathRequest, Option<f32>> for MathRequestHandler {
    fn handle(&mut self, req: MathRequest) -> Option<f32> {
        let result = match req.0 {
            Op::Add(a, b) => Some(a + b),
            Op::Sub(a, b) => Some(a - b),
            Op::Mul(a, b) => Some(a * b),
            Op::Div(a, b) => {
                if b == 0.0 { None } else { Some(a / b) }
            }
        };

        self.0.publish(MathEvent(req.0, result)).expect("publish failed");
        result
    }
}

fn main() {
    let mut mediator = DefaultMediator::builder()
        .add_handler_deferred(MathRequestHandler)
        .subscribe_fn(|event: MathEvent| {
           println!("{:?}", event);
         })
        .build();

    let result = mediator.send(MathRequest(Op::Add(1.0, 2.0))).expect("send failed");
    assert_eq!(result, Some(3.0));
}

异步

需要启用 async 功能。

use mediator::{DefaultAsyncMediator, AsyncMediator, Request};

struct MulRequest(f32, f32);
impl Request<f32> for MulRequest {}

#[tokio::main]
async fn main() {
    let mut mediator = DefaultAsyncMediator::builder()
        .add_handler(|req: MulRequest| async move {
            tokio::time::sleep(std::time::Duration::from_secs(1)).await;
            req.0 * req.1
        })
        .build();

    let result = mediator.send(MulRequest(2.0, 3.0)).await.expect("send failed");
    assert_eq!(result, 6.0);
}

需要启用 streams 功能。

use mediator::{StreamRequest, Event, DefaultAsyncMediator, AsyncMediator, box_stream};
use mediator::futures::{StreamExt, BoxStream};

struct CountdownRequest(u32);
impl StreamRequest for CountdownRequest {
    type Stream = BoxStream<'static, u32>;
    type Item = u32;
}

#[tokio::main]
async fn main() {
    let mut mediator = DefaultAsyncMediator::builder()
        .add_stream_handler_fn(|req: CountdownRequest| box_stream! { yx move =>
            let mut count = req.0;
            while count > 0 {
                tokio::time::sleep(std::time::Duration::from_secs(1)).await;
                yx.yield_one(count);
                count -= 1;
            }
         })
        .build();

    let mut stream = mediator.stream(CountdownRequest(3)).await.expect("stream failed");
    assert_eq!(stream.next().await.unwrap(), 3);
    assert_eq!(stream.next().await.unwrap(), 2);
    assert_eq!(stream.next().await.unwrap(), 1);
    assert_eq!(stream.next().await, None);
}

依赖关系

~0–1.3MB
~23K SLoC