You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust策略模式场景:如何将可变引用用作泛型函数参数

策略模式实现原地排序的修改方案

问题背景

练习策略模式时,希望通过运行时选择的排序函数对Vec进行原地排序(通过可变引用修改),但尝试添加&mut后无法适配代码。

修改后的完整代码

use rand::Rng;

#[derive(Clone)]
pub struct Sorter<F: Fn(&mut Vec<T>), T: Ord + Eq + Copy> {
    sort_strategy: F,
    sort_data: Vec<T>,
}

impl<F: Fn(&mut Vec<T>), T: Ord + Eq + Copy> Sorter<F, T> {
    // 改为可变引用self,原地修改数据,无需返回
    pub fn sort(&mut self) {
        (self.sort_strategy)(&mut self.sort_data);
    }

    pub fn new(sort_strategy: F, sort_data: Vec<T>) -> Sorter<F, T> {
        Sorter {
            sort_strategy,
            sort_data,
        }
    }

    // 方便测试获取数据的辅助方法
    pub fn get_data(&self) -> &Vec<T> {
        &self.sort_data
    }
}

// 冒泡排序改为原地修改,接收&mut Vec<T>
pub fn bubble_sort<T: Eq + PartialOrd>(input_vector: &mut Vec<T>) {
    for _ in 0..input_vector.len() {
        for j in 0..(input_vector.len() - 1) {
            if input_vector[j] > input_vector[j + 1] {
                input_vector.swap(j + 1, j);
            }
        }
    }
}

// 快速排序改为原地修改版本
pub fn quick_sort<T: Eq + PartialOrd + Copy>(input_vector: &mut Vec<T>) {
    if input_vector.len() <= 1 {
        return;
    }

    let pivot = rand::thread_rng().gen_range(0..input_vector.len());
    let pivot_val = input_vector[pivot];
    // 将pivot交换到末尾,方便分区
    input_vector.swap(pivot, input_vector.len() - 1);

    let mut i = 0;
    for j in 0..input_vector.len() - 1 {
        if input_vector[j] <= pivot_val {
            input_vector.swap(i, j);
            i += 1;
        }
    }
    // 将pivot放到正确位置
    input_vector.swap(i, input_vector.len() - 1);

    // 递归排序左右两部分
    let (left, right) = input_vector.split_at_mut(i);
    quick_sort(left);
    quick_sort(&mut right[1..]);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bubble_sort() {
        let mut data = vec![5, 4, 3, 2, 1];
        bubble_sort(&mut data);
        assert_eq!(data, vec![1, 2, 3, 4, 5])
    }

    #[test]
    fn test_quick_sort() {
        let mut data = vec![5, 4, 3, 2, 1];
        quick_sort(&mut data);
        assert_eq!(data, vec![1, 2, 3, 4, 5])
    }

    #[test]
    fn test_strategy_pattern_bubble() {
        let mut sorter = Sorter::new(bubble_sort, vec![5, 4, 3, 2, 1]);
        sorter.sort();
        assert_eq!(sorter.get_data(), &vec![1, 2, 3, 4, 5]);
    }

    #[test]
    fn test_strategy_pattern_quick() {
        let mut sorter = Sorter::new(quick_sort, vec![5, 4, 3, 2, 1]);
        sorter.sort();
        assert_eq!(sorter.get_data(), &vec![1, 2, 3, 4, 5]);
    }
}

关键改动说明

  • 排序函数签名调整:将原来接收Vec<T>返回Vec<T>的形式,改为接收&mut Vec<T>,直接在原向量上修改,避免不必要的克隆,实现原地排序。
  • Sorter结构体泛型约束更新:把F: Fn(Vec<T>) -> Vec<T>改为F: Fn(&mut Vec<T>),适配新的排序函数签名。
  • sort方法修改:将sort方法的参数改为&mut self,内部调用策略函数时传入&mut self.sort_data,无需返回自身,真正实现原地修改。
  • 快速排序优化:将原版本的递归创建新向量改为原地分区排序,更符合原地修改的设计,同时减少内存开销。
  • 辅助方法添加:新增get_data方法用于测试时获取排序后的向量引用,避免转移所有权。

内容的提问来源于stack exchange,提问作者Joseph Stevens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:01:14