如何在Rust中实现抽象工厂?
就像是:
trait Thingy {
fn hallo(&self);
}
trait Factory {
fn make(&self) -> Thingy;
}
//------------------------------
struct AThingy {}
impl Thingy for AThingy {
fn hallo(&self) {
println!("i'm A thingy");
}
}
struct AFactory {}
impl Factory for AFactory {
fn make(&self) -> AThingy {
AThingy{}
}
}
//------------------------------
struct BThingy {}
impl Thingy for BThingy {
fn hallo(&self) {
println!("i'm B thingy");
}
}
struct BFactory {}
impl Factory for BFactory {
fn make(&self) -> BThingy {
BThingy{}
}
}
//------------------------------
#[test]
fn test_factory() {
let aFactory:Factory = AFactory{};
let bFactory:Factory = BFactory{};
aFactory.make().hallo();
bFactory.make().hallo();
}
试图在不同的地方附加 Sized 但都失败了。
回答
您可以使用关联类型。Factory可以有一个关联的类型,称为Output. 您可以添加需要Output实现的边界Thingy:
trait Factory {
type Output: Thingy;
fn make(&self) -> Self::Output;
}
现在AFactory的Output将是AThingy:
impl Factory for AFactory {
type Output = AThingy;
fn make(&self) -> AThingy {
AThingy {}
}
}
和BFactory的Output将是BThingy:
impl Factory for BFactory {
type Output = BThingy;
fn make(&self) -> BThingy {
BThingy {}
}
}
正如@PeterHall 提到的,您无法在 Rust 中处理未定义大小的类型,因此要存储 aFactory您需要使用拥有的指针,例如Box<dyn Factory>:
#[test]
fn test_factory() {
let aFactory: Box<dyn Factory> = Box::new(AFactory {});
let bFactory: Box<dyn Factory> = Box::new(BFactory {});
aFactory.make().hallo();
bFactory.make().hallo();
}
但是,因为Factory有关联类型,所以Output在将其放入特征对象时还必须指定:
#[test]
fn test_factory() {
let aFactory: Box<dyn Factory<Output = AThingy>> = AFactory {};
let bFactory: Box<dyn Factory<Output = BThingy>> = BFactory {};
aFactory.make().hallo();
bFactory.make().hallo();
}