Rust 结构模式,在 hashmap 中存储多个工厂
Rust fabric pattern, storing multiple factories in hashmap
我希望能够将多个工厂存储在一个 hashmap 中,以便稍后将它们添加到其中(例如通过插件),然后在应用程序中通过键名获取每个工厂(这是一个资源管理器) .
问题出在 Fabric 特性的泛型上,Fabric 可以创造不同类型的水果,但我需要在这里指定一些东西 HashMap<String, Box<dyn Fabric>>
,例如 HashMap<String, Box<Fabric<Apple>>>
或 HashMap<String, Box<Fabric<T>>>
这是也不是很有用,因为正如我所说,我们可以创造出真正不同的水果。
另外我猜 foo 方法可能有问题,关于借用内容。
那么你将如何实现这个 "the rust way"?
use std::collections::HashMap;
trait Fruit {
fn get_name(&self) -> String;
}
trait Fabric<T: Fruit> {
fn build(&self) -> Box<T>;
}
struct Banana {}
impl Fruit for Banana {
fn get_name(&self) -> String { String::from("I'm banana") }
}
struct BananaFabric {}
impl Fabric<Banana> for BananaFabric {
fn build(&self) -> Box<Banana> {
Box::new(Banana {})
}
}
struct Apple {}
impl Fruit for Apple {
fn get_name(&self) -> String { String::from("I'm apple") }
}
struct AppleFabric {}
impl Fabric<Apple> for AppleFabric {
fn build(&self) -> Box<Apple> {
Box::new(Apple {})
}
}
struct C {
map: HashMap<String, Box<dyn Fabric>>,
}
impl C {
pub fn new() -> C {
C {
map: HashMap::new()
}
}
pub fn foo(&self, key: String) {
match self.map.get(&key) {
Some(&fabric) => {
let fruit = fabric.build();
println!("{}", fruit.get_name())
},
_ => println!("No fabric found")
}
}
}
fn main() {
let c = C::new();
c.foo(String::from("bar"));
}
你的意思是像
use std::collections::HashMap;
trait A {
fn boo(&self) -> i32;
}
struct B {}
impl A for B {
fn boo(&self) -> i32 {
15
}
}
struct C {
map: HashMap<String, Box<dyn A>>,
}
impl C {
pub fn new() -> C {
C {
map: HashMap::new(),
}
}
pub fn foo(&self, key: String) {
match self.map.get(&key) {
Some(val) => println!("{}", val.boo()),
_ => println!("None"),
}
}
}
fn main() {
let mut c = C::new();
c.map.insert(String::from("bar"), Box::new(B{}));
c.foo(String::from("bar"));
}
顺便说一句。这是 Factory Design Pattern
.
我能想到两个方案:
动态调度(特征对象):
trait Fabric {
fn build(&self) -> Box<dyn Fruit>;
}
[...]
impl Fabric for BananaFabric {
fn build(&self) -> Box<dyn Fruit> {
Box::new(Banana {})
}
}
使用 enum
:
enum Fruits {
Banana,
Apple
}
impl Fruit for Fruits {
fn get_name(&self) -> String {
match self {
Banana => String::from("I'm banana"),
Apple => String::from("I'm apple"),
_ => String::from("")
}
}
}
[...]
impl Fabric for BananaFabric {
fn build(&self) -> Box<Fruits> {
Box::new(Fruits::Banana)
}
}
在这两种情况下,foo
方法将如下所示:
pub fn foo(&self, key: String) {
match self.map.get(&key) {
Some(fabric) => {
let fruit = fabric.build();
println!("{}", fruit.get_name())
},
_ => println!("No fabric found")
}
}
我希望能够将多个工厂存储在一个 hashmap 中,以便稍后将它们添加到其中(例如通过插件),然后在应用程序中通过键名获取每个工厂(这是一个资源管理器) .
问题出在 Fabric 特性的泛型上,Fabric 可以创造不同类型的水果,但我需要在这里指定一些东西 HashMap<String, Box<dyn Fabric>>
,例如 HashMap<String, Box<Fabric<Apple>>>
或 HashMap<String, Box<Fabric<T>>>
这是也不是很有用,因为正如我所说,我们可以创造出真正不同的水果。
另外我猜 foo 方法可能有问题,关于借用内容。
那么你将如何实现这个 "the rust way"?
use std::collections::HashMap;
trait Fruit {
fn get_name(&self) -> String;
}
trait Fabric<T: Fruit> {
fn build(&self) -> Box<T>;
}
struct Banana {}
impl Fruit for Banana {
fn get_name(&self) -> String { String::from("I'm banana") }
}
struct BananaFabric {}
impl Fabric<Banana> for BananaFabric {
fn build(&self) -> Box<Banana> {
Box::new(Banana {})
}
}
struct Apple {}
impl Fruit for Apple {
fn get_name(&self) -> String { String::from("I'm apple") }
}
struct AppleFabric {}
impl Fabric<Apple> for AppleFabric {
fn build(&self) -> Box<Apple> {
Box::new(Apple {})
}
}
struct C {
map: HashMap<String, Box<dyn Fabric>>,
}
impl C {
pub fn new() -> C {
C {
map: HashMap::new()
}
}
pub fn foo(&self, key: String) {
match self.map.get(&key) {
Some(&fabric) => {
let fruit = fabric.build();
println!("{}", fruit.get_name())
},
_ => println!("No fabric found")
}
}
}
fn main() {
let c = C::new();
c.foo(String::from("bar"));
}
你的意思是像
use std::collections::HashMap;
trait A {
fn boo(&self) -> i32;
}
struct B {}
impl A for B {
fn boo(&self) -> i32 {
15
}
}
struct C {
map: HashMap<String, Box<dyn A>>,
}
impl C {
pub fn new() -> C {
C {
map: HashMap::new(),
}
}
pub fn foo(&self, key: String) {
match self.map.get(&key) {
Some(val) => println!("{}", val.boo()),
_ => println!("None"),
}
}
}
fn main() {
let mut c = C::new();
c.map.insert(String::from("bar"), Box::new(B{}));
c.foo(String::from("bar"));
}
顺便说一句。这是 Factory Design Pattern
.
我能想到两个方案:
动态调度(特征对象):
trait Fabric {
fn build(&self) -> Box<dyn Fruit>;
}
[...]
impl Fabric for BananaFabric {
fn build(&self) -> Box<dyn Fruit> {
Box::new(Banana {})
}
}
使用 enum
:
enum Fruits {
Banana,
Apple
}
impl Fruit for Fruits {
fn get_name(&self) -> String {
match self {
Banana => String::from("I'm banana"),
Apple => String::from("I'm apple"),
_ => String::from("")
}
}
}
[...]
impl Fabric for BananaFabric {
fn build(&self) -> Box<Fruits> {
Box::new(Fruits::Banana)
}
}
在这两种情况下,foo
方法将如下所示:
pub fn foo(&self, key: String) {
match self.map.get(&key) {
Some(fabric) => {
let fruit = fabric.build();
println!("{}", fruit.get_name())
},
_ => println!("No fabric found")
}
}