简体   繁体   English

创建一个返回空结构实现的工厂类

[英]Create a factory class that returns an empty-struct implementation

I'd like to create a common interface for formatters, that will take the input and format it according to their purpose. 我想为格式化程序创建一个通用接口,它将根据其目的进行输入和格式化。

Currently I'm returning a Box containing the formatter implementation (wrapped into a Result). 目前我正在返回一个包含格式化程序实现的Box(包含在Result中)。 But I don't think this is the best way to do it. 但我不认为这是最好的方法。 Since the Formatter implementations are empty structs, allocating heap memory for a Box doesn't make sense. 由于Formatter实现是空结构,因此为Box分配堆内存没有意义。

pub trait Formatter {
    fn format_information(&self, information: Result<Information, Error>) -> Result<String, Error>;
    fn format_information_collection(&self, information: InformationCollection) -> Result<String, Error>;
}

pub struct JsonFormatter;
impl Formatter for JsonFormatter {...}

pub struct XmlFormatter;
impl Formatter for XmlFormatter {...}


// Factory to create a formatter
pub struct Factory;
impl Factory {
    pub fn get_formatter(format: &str) -> Result<Box<Formatter>, Error> {
        match format {
            "json" => Ok(Box::new(JsonFormatter {})),
            "xml" => Ok(Box::new(XmlFormatter {})),
            _ => Err(Error::new(format!("No formatter found for format {}", format)))
        }
    }
}

// Use the factory
let formatter_box = Factory::get_formatter(format).unwrap();
let formatter = &*formatter_box as &Formatter;

What's the correct way to do this in Rust? 在Rust中这样做的正确方法是什么?

Since the Formatter implementations are empty structs, allocating heap memory for a Box doesn't make sense. 由于Formatter实现是空结构,因此为Box分配堆内存没有意义。

And since it doesn't make any sense, heap memory won't be allocated at all. 而且由于它没有任何意义,因此根本不会分配堆内存。 Let's try it ( Playground ): 我们来试试吧( 游乐场 ):

// `()` doesn't occupy any space, like e.g. your `JsonFormatter`
let b1 = Box::new(());
let b2 = Box::new(());

println!("{:p}\n{:p}", &*b1, &*b2);

This produces the output: 这会产生输出:

0x1
0x1

ZSTs (zero sized types) are often treated in a special way. ZST(零大小类型)通常以特殊方式处理。 So at least you know you aren't paying for heap allocations here. 所以至少你知道你不支付堆分配。 Note however, that the memory layout of your Box<Formatter> is a fat pointer and looks like this: (*mut Formatter, *mut VTable) . 但请注意, Box<Formatter>的内存布局是一个胖指针,如下所示: (*mut Formatter, *mut VTable) The first pointer always being 0x1 , the second one pointing to a statically allocated dispatch table which contains function pointer ( vtable - Wikipedia ). 第一个指针始终为0x1 ,第二个指针指向静态分配的包含函数指针( vtable - Wikipedia )的调度表。 This is probably fine in your situation. 这在你的情况下可能很好。


Another possibility is to create an enum like this: 另一种可能性是创建一个这样的枚举:

enum FormatterSd {
    Json(JsonFormatter),
    Xml(XmlFormatter),
}

And now you can implement Formatter for FormatterSd ; 现在你可以Formatter for FormatterSd实现Formatter for FormatterSd ; in this implementation you will use simple match blocks to do dispatch. 在此实现中,您将使用简单的match块来执行调度。 That way you don't need to use Box . 这样你就不需要使用Box


Lastly: you don't need to have a factory type! 最后:您不需要工厂类型! It seems a bit like you are trying to bring ideas from a strongly OO programming language into Rust. 看起来有点像你试图将强大的OO编程语言中的想法带入Rust。 Often, this is not the best or most idiomatic solution. 通常,这不是最佳或最惯用的解决方案。 For example, there are free functions in Rust. 例如,Rust中有自由函数。 So you can simply write: 所以你可以简单地写:

fn get_formatter(format: &str) -> Result<Box<Formatter>, Error> {
    // ...
}

Yes, without the Factory type! 是的,没有Factory类型! Empty types are a lot less common in Rust than empty classes (meaning: without any fields). Rust中的空类型比空类少得多(意思是:没有任何字段)。 You can just use free function for this kind of stuff, there is no need to associate it with a type. 你可以只为这种东西使用自由函数,不需要将它与一个类型相关联。

And lastly lastly: you don't need to manually obtain a reference from a Box : 最后:您不需要从Box手动获取引用:

let formatter = &*formatter_box as &Formatter;

You can simple say formatter_box.format_information(...); 你可以简单地说formatter_box.format_information(...); , thanks to deref coercions. ,多亏了deref强制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM