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
相关产品推荐
相关产品推荐

