[英]Create a factory class that returns an empty-struct implementation
我想為格式化程序創建一個通用接口,它將根據其目的進行輸入和格式化。
目前我正在返回一個包含格式化程序實現的Box(包含在Result中)。 但我不認為這是最好的方法。 由於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;
在Rust中這樣做的正確方法是什么?
由於Formatter實現是空結構,因此為
Box
分配堆內存沒有意義。
而且由於它沒有任何意義,因此根本不會分配堆內存。 我們來試試吧( 游樂場 ):
// `()` doesn't occupy any space, like e.g. your `JsonFormatter`
let b1 = Box::new(());
let b2 = Box::new(());
println!("{:p}\n{:p}", &*b1, &*b2);
這會產生輸出:
0x1
0x1
ZST(零大小類型)通常以特殊方式處理。 所以至少你知道你不支付堆分配。 但請注意, Box<Formatter>
的內存布局是一個胖指針,如下所示: (*mut Formatter, *mut VTable)
。 第一個指針始終為0x1
,第二個指針指向靜態分配的包含函數指針( vtable - Wikipedia )的調度表。 這在你的情況下可能很好。
另一種可能性是創建一個這樣的枚舉:
enum FormatterSd {
Json(JsonFormatter),
Xml(XmlFormatter),
}
現在你可以Formatter for FormatterSd
實現Formatter for FormatterSd
; 在此實現中,您將使用簡單的match
塊來執行調度。 這樣你就不需要使用Box
。
最后:您不需要工廠類型! 看起來有點像你試圖將強大的OO編程語言中的想法帶入Rust。 通常,這不是最佳或最慣用的解決方案。 例如,Rust中有自由函數。 所以你可以簡單地寫:
fn get_formatter(format: &str) -> Result<Box<Formatter>, Error> {
// ...
}
是的,沒有Factory
類型! Rust中的空類型比空類少得多(意思是:沒有任何字段)。 你可以只為這種東西使用自由函數,不需要將它與一個類型相關聯。
最后:您不需要從Box
手動獲取引用:
let formatter = &*formatter_box as &Formatter;
你可以簡單地說formatter_box.format_information(...);
,多虧了deref強制。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.