【问题标题】:Design patterns without the box没有盒子的设计模式
【发布时间】:2022-11-27 07:34:19
【问题描述】:

Rust 初学者在这里。我有许多几乎相同的算法,但在最后一步,它们都以略有不同的方式汇总结果。假设 Algorithm 执行以下操作:

pub struct Algorithm<T> {
    result_aggregator: Box<dyn ResultAggregator<T>>,
}

impl<T> Algorithm<T> {
    pub fn calculate(&self, num1: i32, num2: i32) -> T {
        let temp = num1 + num2;
        self.result_aggregator.create(temp)
    }
}

有了这个,我可以创建几个不同的结果聚合器类来获取我的临时结果并将其转换为我的最终结果:

pub trait ResultAggregator<T> {
    fn create(&self, num: i32) -> T;
}

pub struct FloatAggregator;
pub struct StringAggregator;

impl ResultAggregator<f32> for FloatAggregator {
    fn create(&self, num: i32) -> f32 {
        num as f32 * 3.14159
    }
}

impl ResultAggregator<String> for StringAggregator {
    fn create(&self, num: i32) -> String {
        format!("~~{num}~~")
    }
}

...并这样称呼它:

fn main() {
    // Here's a float example
    let aggregator = FloatAggregator;
    let algorithm = Algorithm {
        result_aggregator: Box::new(aggregator),
    };

    let result = algorithm.calculate(4, 5);
    println!("The result has value {result}");
    
    // Here's a string example
    let aggregator = StringAggregator;
    let algorithm = Algorithm {
        result_aggregator: Box::new(aggregator),
    };

    let result = algorithm.calculate(4, 5);
    println!("The result has value {result}");
}

这就是我想出的。

问题:没有动态框是否可以做到这一点?它对性能至关重要,我知道泛型通常是一个很好的解决方案,但我没有运气弄清楚如何在没有动态调度的情况下让它工作。

那么这个问题的 Rusty 解决方案是什么?我觉得我正在用我的 C# 帽子接近它,这可能不是要走的路。

Link to the playground

【问题讨论】:

    标签: rust strategy-pattern dynamic-dispatch


    【解决方案1】:

    您可以使用关联类型而不是泛型参数:

    pub trait ResultAggregator {
        type Output;
        fn create(&self, num: i32) -> Self::Output;
    }
    
    pub struct FloatAggregator;
    pub struct StringAggregator;
    
    impl ResultAggregator for FloatAggregator {
        type Output = f32;
        fn create(&self, num: i32) -> f32 {
            num as f32 * 3.14159
        }
    }
    
    impl ResultAggregator for StringAggregator {
        type Output = String;
        fn create(&self, num: i32) -> String {
            format!("~~{num}~~")
        }
    }
    
    pub struct Algorithm<Aggregator> {
        result_aggregator: Aggregator,
    }
    
    impl<Aggregator: ResultAggregator> Algorithm<Aggregator> {
        pub fn calculate(&self, num1: i32, num2: i32) -> Aggregator::Output {
            let temp = num1 + num2;
            self.result_aggregator.create(temp)
        }
    }
    

    【讨论】:

    • 很棒的解决方案。谢谢你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    相关资源
    最近更新 更多