2017-04-27 41 views
3

我想爲格式化程序創建一個通用接口,它將根據其用途來接受輸入並進行格式化。創建一個返回空結構實現的工廠類

目前我正在返回包含格式化程序實現(包裝到結果中)的Box。但我認爲這不是最好的方式。由於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中做到這一點的正確方法?

回答

10

由於Formatter實現是空結構,爲Box分配堆內存沒有任何意義。

而且由於沒有任何意義,堆內存將不會被分配。讓我們試一下(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); 

這將產生輸出:

0x1 
0x1 

ZSTs(零種大小類型),以特殊的方式往往對待。所以至少你知道你不會在這裏支付堆分配。但請注意,您的Box<Formatter>的內存佈局是一個胖指針,看起來像這樣:(*mut Formatter, *mut VTable)。第一個指針始終爲0x1,第二個指針指向包含函數指針(vtable - Wikipedia)的靜態分配調度表。這在你的情況下可能很好。


另一種可能性是創建這樣一個枚舉:

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

現在你可以實現Formatter for FormatterSd;在這個實現中,您將使用簡單的match塊來進行分派。這樣你就不需要使用Box


最後:你不需要有工廠類型!看起來有點像你正試圖將一種強烈的面向對象編程語言的想法帶入Rust。通常情況下,這不是最好或最習慣的解決方案。例如,Rust中有免費的功能。所以你可以簡單地寫:

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

是的,沒有Factory類型!空的類型在空白類中比空類更不常見(意思是:沒有任何字段)。你可以使用這種類型的自由函數,不需要將它與一個類型關聯。

而且最後最後:你不需要從Box手動獲得一個參考:

let formatter = &*formatter_box as &Formatter; 

你可以簡單的說formatter_box.format_information(...);,感謝DEREF的強制。

+0

謝謝你的回答。我學到了很多。我從Rust開始,我的工作日語言是PHP :) – cundd