设计思路
- 存储不同类型的
Fn
实例:使用 Box<dyn Fn()>
来存储不同类型但都实现了 Fn
trait 的实例。Box<dyn Trait>
这种形式可以实现动态分发,允许我们在运行时处理不同类型的对象。
- 调度逻辑:在调度器中,我们可以使用一个
Vec<Box<dyn Fn()>>
来存储这些实例。根据运行时的条件,我们从这个向量中选择合适的实例并调用它。
- 错误处理机制:由于
Fn
trait 本身不支持返回错误,我们可以通过包裹闭包,将错误处理逻辑添加进去。例如,使用 Result
类型来处理可能的错误。
代码实现
use std::fmt::Debug;
// 调度器结构体
struct Scheduler {
handlers: Vec<Box<dyn Fn() -> Result<(), String>>>,
}
impl Scheduler {
// 添加处理函数
fn add_handler<F>(&mut self, handler: F)
where
F: 'static + Fn() -> Result<(), String>,
{
self.handlers.push(Box::new(handler));
}
// 根据索引调用处理函数
fn execute(&self, index: usize) -> Result<(), String> {
if index >= self.handlers.len() {
return Err("Index out of bounds".to_string());
}
(self.handlers[index])()
}
}
// 示例自定义结构体
struct Handler1;
impl Handler1 {
fn new() -> Self {
Handler1
}
}
impl Fn() -> Result<(), String> for Handler1 {
fn call(&self) -> Result<(), String> {
println!("Handler1 executed");
Ok(())
}
}
struct Handler2;
impl Handler2 {
fn new() -> Self {
Handler2
}
}
impl Fn() -> Result<(), String> for Handler2 {
fn call(&self) -> Result<(), String> {
println!("Handler2 executed");
Ok(())
}
}
fn main() {
let mut scheduler = Scheduler { handlers: Vec::new() };
scheduler.add_handler(Handler1::new());
scheduler.add_handler(Handler2::new());
match scheduler.execute(0) {
Ok(_) => (),
Err(e) => eprintln!("Error: {}", e),
}
}
代码说明
Scheduler
结构体:包含一个 Vec<Box<dyn Fn() -> Result<(), String>>>
类型的 handlers
字段,用于存储不同类型的处理函数。
add_handler
方法:用于向调度器中添加处理函数。这里使用了泛型 F
,并约束 F
实现 Fn() -> Result<(), String>
以及具有 'static
生命周期。
execute
方法:根据传入的索引,调用对应的处理函数。如果索引超出范围,返回错误。
- 自定义结构体
Handler1
和 Handler2
:都实现了 Fn() -> Result<(), String>
trait,模拟不同类型的处理函数。在 main
函数中,创建调度器实例,添加处理函数,并执行其中一个处理函数。错误处理通过 Result
类型来实现。这样设计使得代码具有良好的可读性和扩展性,便于后续添加更多类型的处理函数。