2012-12-14 93 views
2

我目前正在研究「保存」機制,它允許用戶保存他在硬盤上工作的項目。輸出將是一個包含各種數據的XML文件。
現在我們的項目結構即將改變,我們需要編寫一個新的XML文件(創建一個新的保存方法)。
所以現在遇到挑戰:保存時我希望用戶能夠選擇他將要創建的文件格式(版本1(舊)或版本2(新))。
現在有人如何做到這一點?有沒有適合的設計模式?
備註: - 我們保存的數據可以看作是不相關的塊,所以實際上很容易將舊塊與新塊交換。 - 這件事的整個目標是,加載一箇舊項目時應該再次可讀。 (我認爲這可以通過標籤完成,並在加載時對標籤做出反應?)「保存」的設計模式

+0

[策略](http://en.wikipedia.org/wiki/Strategy_pattern)聽起來像你想要的。 – StoryTeller

+1

[boost :: serialization](http://www.boost.org/doc/libs/1_52_0/libs/serialization/doc/index.html)可用於將對象保存爲xml格式。 – andre

+0

從某種意義上說,Google Protocol Buffers和Facebook Thrift試圖解決同樣的問題...... –

回答

3

這聽起來像是一個很好的Strategy模式應用程序。

您將創建兩個虛函數,projectToXmlxmlToProject,這是爲了把你的內部項目表示成XML,反之亦然一個抽象基類FileFormat(策略接口)。

然後,您創建兩個執行子類FileFormatNewFileFormatLegacy(這些是具體策略)。

然後,您的保存功能將另外需要一個FileFormat實例,並調用該對象的相應方法來執行數據轉換。您的加載函數可以通過檢查XML樹中的某些內容來選擇要使用的策略,以告知它是哪個版本。

當你需要支持另一種文件格式時,你只需要創建一個新的類,它是FileFormat的子類。在意見交換後

附錄

當你將有很多版本,具有非常小的差異,但您仍想使用的策略模式,你可以做的FileFormat多的複合策略:CircleStragegy,RectangleStrategy,LineStrategy等。在這種情況下,我不會爲FileFormat的不同版本使用不同的類。我會爲每個版本創建一個靜態工廠函數,該函數返回一個帶有該版本中使用的Strategy對象的FileFormat。

FileFormat FileFormat::createVersion1_0() { 
    return new FileFormat(
     new LineStrategyOld(), 
     new CircleStrategyOld(), 
     new RectangleStragegyOld() 
    ); 
} 

FileFormat FileFormat::createVersion1_1() { 
    // the 1.1 version introduced the new way to save lines 
    return new FileFormat(   
     new LineStrategyNew(), 
     new CircleStrategyOld(), 
     new RectangleStragegyOld() 
    ); 
} 

FileFormat FileFormat::createVersion1_2() { 
    // 1.2 uses the new format to save circles 
    return new FileFormat(   
     new LineStrategyNew(), 
     new CircleStrategyNew(), 
     new RectangleStragegyOld() 
    ); 
} 

FileFormat FileFormat::createVersion1_3() { 
    // 1.3 uses a new format to save rectangles, but we realized that 
    // the new way to save lines wasn't that good after all, so we 
    // returned to the old way. 
    return new FileFormat(   
     new LineStrategyOld(), 
     new CircleStrategyNew(), 
     new RectangleStragegyNew() 
    ); 
} 

注:在實際的代碼,當然你可以使用比「老」和「新」更多描述後綴爲你的策略類名。

+0

所以基本上每個對象都負責提供xml數據?這意味着我不會有一個大的方法收集所有使用公共getter和setter爲不同的成員,但相反,我會調用一個方法「getAppropriateData()」,我會從對象本身獲取數據? 而採用這種方法,我甚至可以爲兩個保存版本之間最小的變化需要一個新的具體策略,除了一個微小的變化,它調用所有相同的功能,除了一個微小的變化,對吧? – Donny

+0

應始終避免使用冗餘代碼。當兩種策略非常相似並且只是在一些細節上有所不同時,任何一個都可以從另一個繼承,或者可以將大部分代碼移到基類的通用私有函數中,而只執行每個派生中真正不同的部分類。 – Philipp

+0

關於如何收集您的策略需要保存的數據:我需要知道您的數據是如何構建的,以便爲此提供任何建議。當你想避免通過讓getter獲取需要保存的所有內容來暴露你的項目類的太多細節時,你可以使用Visitor模式來收集數據。 http://en.wikipedia.org/wiki/Visitor_pattern – Philipp