Rust “的适当所有权”;“缓存代理”;锈迹斑斑?
我想使用Rust “的适当所有权”;“缓存代理”;锈迹斑斑?,rust,traits,ownership,Rust,Traits,Ownership,我想使用工厂从字符串构建一个对象,并具有多个impl:1)实际构建和2)缓存(存储在HashMap中的内存中)。问题是,在案例1中,它必须传递所有权,而在案例2中,HashMap拥有该值,并且只能返回一个引用 use std::collections::HashMap; // product interface pub trait TProduct { fn get_title(&self) -> &String; } // and concrete impl
工厂
从字符串
构建一个对象,并具有多个impl:1)实际构建和2)缓存(存储在HashMap
中的内存中)。问题是,在案例1中,它必须传递所有权,而在案例2中,HashMap拥有该值,并且只能返回一个引用
use std::collections::HashMap;
// product interface
pub trait TProduct {
fn get_title(&self) -> &String;
}
// and concrete impls
pub struct ConcreteProduct1 {
}
impl TProduct for ConcreteProduct1 {
// ...
}
pub struct ConcreteProduct2 {
}
impl TProduct for ConcreteProduct2 {
// ...
}
// factory interface
pub trait TProductFactory {
fn product_from_text(&mut self, text: String) -> Box<dyn TProduct>;
// QUESTION: should it be Box (required for ProductFactory) or &Box (required for ProductCachingProxy)?
}
// actual building factory
pub struct ProductFactory {
}
impl TProductFactory for ProductFactory {
fn product_from_text(&mut self, text: String) -> Box<dyn TProduct> {
//...
// depending on some conditions
Box::new(ConcreteProduct1::from_text(text)); // has to pass the ownership
// or
Box::new(ConcreteProduct2::from_text(text)); // has to pass the ownership
//...
}
}
// caching proxy
trait TProductCache {
fn put(&mut self, text: &String, product: Box<dyn TProduct>);
fn get(&self, text: &String) -> Option<&Box<dyn TProduct>>;
fn clear(&mut self);
}
struct InMemoryProductCache {
map: HashMap<String, Box<dyn TProduct>>
}
impl InMemoryProductCache {
fn new() -> Self {
return InMemoryProductCache {
map: HashMap::new()
}
}
}
impl TProductCache for InMemoryProductCache {
fn put(&mut self, text: &String, product: Box<dyn TProduct>) {
self.map.insert(text.to_string(), product);
}
fn get(&self, text: &String) -> Option<&Box<dyn TProduct>> {
return match self.map.get(text) {
Some(boxed_product) => Some(boxed_product), // have to pass a reference to let it still own the value
None => None
}
}
fn clear(&mut self) {
self.map.clear();
}
}
struct ProductCachingProxy {
product_factory: Box<dyn TProductFactory>,
cache: Box<dyn TProductCache>
}
impl ProductCachingProxy {
fn new_for_factory(product_factory: Box<dyn TProductFactory>, cache: Box<dyn TProductCache>) -> Self {
return ProductCachingProxy {
product_factory,
cache
}
}
}
impl TProductFactory for ProductCachingProxy {
fn product_from_text(&mut self, text: String) -> &Box<dyn TProduct> { // can't pass ownership
let boxed_product = match self.cache.get(&text) {
Some(found_boxed_product) => found_boxed_product,
_ => {
// delegate creation to wrapped TProductFactory impl (`product_factory`)
let boxed_product = self.product_factory.product_from_text(text.clone());
// ... and put to the cache
self.cache.put(&text, boxed_product);
&boxed_product
}
};
return boxed_product;
}
}
使用std::collections::HashMap;
//产品界面
公共产品{
fn获取标题(&self)->&String;
}
//和混凝土
发布结构ConcreteProduct1{
}
针对ConcreteProduct1的impl TProduct{
// ...
}
发布结构ConcreteProduct2{
}
针对ConcreteProduct2的impl TProduct{
// ...
}
//工厂接口
酒吧生产厂{
fn product_from_text(&mut self,text:String)->Box;
//问题:应该是Box(ProductFactory需要)还是&Box(ProductCachingProxy需要)?
}
//实际建筑工厂
pub结构产品工厂{
}
为ProductFactory导入ProductFactory{
fn product\u from\u text(&mut self,text:String)->Box{
//...
//取决于某些条件
Box::new(ConcreteProduct1::from_text(text));//必须传递所有权
//或
Box::new(ConcreteProduct2::from_text(text));//必须传递所有权
//...
}
}
//缓存代理
特征产品缓存{
fn put(&mut self,文本:&String,产品:框);
fn get(&self,text:&String)->选项;
fn清除(&mut self);
}
结构InMemoryProductCache{
映射:HashMap
}
impl InMemoryProductCache{
fn new()->Self{
返回内存产品缓存{
map:HashMap::new()
}
}
}
InMemoryProductCache的impl TProductCache{
fn put(&mut self,文本:&String,产品:框){
self.map.insert(text.to_string(),product);
}
fn get(&self,text:&String)->选项{
返回匹配self.map.get(文本){
Some(boxed_product)=>Some(boxed_product),//必须传递一个引用以使其仍然拥有该值
无=>无
}
}
fn清除(&M自我){
self.map.clear();
}
}
结构ProductCachingProxy{
产品出厂:包装箱,
缓存:框
}
impl ProductCachingProxy{
fn新工厂(产品工厂:盒子,缓存:盒子)->Self{
退货产品CachingProxy{
产品制造厂,
隐藏物
}
}
}
ProductCachingProxy的impl TProductFactory{
fn product_from_text(&mut self,text:String)->&Box{//无法传递所有权
让boxed_product=匹配self.cache.get(&text){
一些(发现的盒装产品)=>发现的盒装产品,
_ => {
//将创建委托给包装的TProductFactory impl(`product\u factory`)
让boxed_product=self.product_factory.product_from_text(text.clone());
//…并放入缓存
self.cache.put(文本和盒装产品);
&盒装产品
}
};
退回盒装产品;
}
}
//问题:从TProductFactory.fn product\u from_text(&mut self,text:String)->框返回的是Box
(ProductFactory需要)还是&Box
(ProductCachingProxy需要)代码>
如果缓存代理返回框
,如何从引用创建它而不复制/克隆(TProductCache.get(…)
)?将框
替换为Rc
(或者Arc
,如果使用线程)。它提供共享所有权,并为您的两个案例提供单一签名。另一种选择是使用Cow
,这是一个拥有和借用状态的枚举。在性能方面,什么是首选(Rc vs Cow)?@4ntoine Cow意味着在使用它时只需检查一下,Rc维护参考计数器。更重要的区别是,Cow在任何地方都需要合适的寿命,而使用Rc时,你可以忘记它们。