Rust中如何将Adapter结构体缓存抽象为Cache trait实现
重构方案
1. 扩展Cache Trait
首先给Cache trait添加缓存访问方法,让所有实现该trait的类型提供统一的访问接口,避免直接依赖内部结构:
pub trait Cache { // 保留原有插入方法 fn insert(&mut self, data: Budgets) -> anyhow::Result<()>; // 添加获取预算的统一方法 fn get(&self, budget_name: &str) -> Option<&Budget>; }
2. 完善HashCache实现
让HashCache实现新增的get方法,封装内部HashMap的访问逻辑:
use std::collections::HashMap; pub struct HashCache { cache: HashMap<String, Budget>, } impl Cache for HashCache { fn insert(&mut self, data: Budgets) -> anyhow::Result<()> { for budget in data.budgets.into_iter() { self.cache.insert(budget.name.clone(), budget); } Ok(()) } fn get(&self, budget_name: &str) -> Option<&Budget> { self.cache.get(budget_name) } } // 给HashCache添加独立构造函数,简化实例创建 impl HashCache { pub fn new() -> Self { HashCache { cache: HashMap::new() } } }
3. 泛化Adapter构造逻辑
让Adapter支持任意Cache实现,同时保留默认使用HashCache的快捷构造方式:
pub struct Adapter<'a, T: Cache> { base_uri: &'a str, client: reqwest::blocking::Client, default_budget: Option<&'a str>, cache: T, } // 通用构造逻辑:适配所有Cache类型 impl<'a, T: Cache> Adapter<'a, T> { // 自定义缓存的构造函数 pub fn with_cache(bearer: String, cache: T) -> Self { let client = reqwest::blocking::Client::builder() .bearer_auth(bearer) .build() .expect("Failed to initialize HTTP client"); Adapter { base_uri: "https://your-api-base-uri.com", // 替换为实际API地址 client, default_budget: None, cache, } } // 重构show_accounts,通过Cache trait方法访问数据,消除嵌套调用 pub fn show_accounts(&self, budget_name: &str) { match self.cache.get(budget_name) { Some(budget) => { if let Some(accounts) = &budget.accounts { println!("{:?}", accounts); } else { println!("No accounts present"); } } None => println!("Budget '{}' not found in cache", budget_name), } } } // 默认构造函数:使用HashCache作为缓存 impl<'a> Adapter<'a, HashCache> { pub fn new(bearer: String) -> Self { Self::with_cache(bearer, HashCache::new()) } }
可选:动态分发模式(无泛型参数)
如果不想让Adapter携带泛型参数,可使用Box<dyn Cache>实现动态分发,更接近传统“接口”模式:
pub struct Adapter<'a> { base_uri: &'a str, client: reqwest::blocking::Client, default_budget: Option<&'a str>, cache: Box<dyn Cache>, } impl<'a> Adapter<'a> { pub fn new(bearer: String) -> Self { Self::with_cache(bearer, Box::new(HashCache::new())) } pub fn with_cache(bearer: String, cache: Box<dyn Cache>) -> Self { let client = reqwest::blocking::Client::builder() .bearer_auth(bearer) .build() .expect("Failed to initialize HTTP client"); Adapter { base_uri: "https://your-api-base-uri.com", client, default_budget: None, cache, } } pub fn show_accounts(&self, budget_name: &str) { match self.cache.get(budget_name) { Some(budget) => { if let Some(accounts) = &budget.accounts { println!("{:?}", accounts); } else { println!("No accounts present"); } } None => println!("Budget '{}' not found in cache", budget_name), } } }
使用示例
fn main() -> anyhow::Result<()> { // 使用默认HashCache let mut adapter = Adapter::new("your-bearer-token".to_string()); // 模拟插入数据 let budgets = Budgets { budgets: vec![Budget { name: "MyBudget".to_string(), accounts: Some(vec![]) }] }; adapter.cache.insert(budgets)?; adapter.show_accounts("MyBudget"); // 使用自定义缓存(比如自己实现的AnotherCache) // let custom_cache = AnotherCache::new(); // let mut adapter = Adapter::with_cache("your-bearer-token".to_string(), custom_cache); Ok(()) }
内容的提问来源于stack exchange,提问作者seve
相关产品推荐
相关产品推荐

