2017-07-24 129 views
0

我想就如何解決以下問題提出建議。不變類的設計模式建議

首先我有這些類是可變的。重要的類是包含作爲字節數組的圖像的ImageData。

public class RootData 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public ImageData Image { get; set; } 
    public List<ChildData> Children { get; set; } 
} 

public class ChildData 
{ 
    public string Name { get; set; } 
    public ImageData Image { get; set; } 
} 

public class ImageData 
{ 
    public string Extension { get; set; } 
    public byte[] Data { get; set; } 
} 

類的第二個設置是這些,它們是不可變的。重要的類是ImageInfo,它包含磁盤上圖像的文件路徑。

public class RootInfo 
{ 
    private RootInfo() 
    { 
    } 

    public string Name 
    { 
     get { return this.name; } 
    } 

    public string Description 
    { 
     get { return this.description; } 
    } 

    public ImageInfo Image 
    { 
     get { return this.image; } 
    } 

    public IEnumerable<ChildInfo> Children 
    { 
     get { return this.children; } 
    } 

    public static RootInfo ToInfo(RootData rootData) 
    { 
    } 

    private readonly string name; 
    private readonly string description; 
    private readonly ImageInfo image; 
    private IEnumerable<ChildInfo> children; 
} 

public class ChildInfo 
{ 
    public string Name 
    { 
     get { return this.name; } 
    } 

    public ImageInfo Image 
    { 
     get { return this.image; } 
    } 

    private readonly string name; 
    private readonly ImageInfo image; 
} 

public class ImageInfo 
{ 
    public string Path 
    { 
     get { return this.path; } 
    } 

    private readonly string path; 
} 

現在,我想將RootData對象轉換爲RootInfo對象。我首先想到在RootInfo類中創建一個靜態方法(ToInfo),該類使用RootData對象創建一個RootInfo對象。但我不想讓ImageInfo類負責將圖像保存在磁盤上。

對於如何以乾淨的方式解決這個問題,您有什麼建議嗎?

注意:這只是一個例子,實際的類更復雜,但原理是相同的。

+1

如何保存圖像?圖像何時保存? –

+0

你是什麼意思關於「保存磁盤上的圖像」?在你的例子中沒有關於它的代碼。所以目前還不清楚有什麼問題。 – Win4ster

回答

0

好像你有兩套不同的抽象實現。那麼如何定義共享接口(IRootInfo,IChildInfo和IImageInfo)並使每個* Data和* Info類實現相應的接口?每當你需要使用的,例如,根的名字,你將通過接口得到它,如:

public string GetNameOfRoot(IRootInfo root) 
{ 
    return root.Name; 
} 

但不要忘了使用界面,而不是形而下類型的引用:

public List<IChildInfo> Children { get; set; } 
0

更好地考慮接口而不是類。一個類可以實現一個或多個接口,接口可以相互繼承。讓我們先從一個只讀接口:

public interface IReadOnlyRootInfo 
{ 
    string Name { get; } 
    string Description { get; } 
    ImageData Image { get; } 
    List<ChildData> Children { get; } 
} 

接下來,讓我們添加的是一個可寫的版本:

public interface IWritableRootInfo : IReadOnlyRootInfo 
{ 
    new string Name { get; set; } 
    new string Description { get; set; } 
    new ImageData Image { get; set; } 
    List<ChildData> Children { get; set; } 
} 

現在你的具體類實現IWritableRootInfo,從而也IReadOnlyRootInfo

public class RootData : IWritableRootInfo, IReadOnlyRootInfo 
{ 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public ImageData Image { get; set; } 
    public List<ChildData> Children { get; set; } 
} 

現在只需將其實際爲RootData的對象作爲IWritableRootInfoIReadOnlyRootInfo傳遞給其他方法。

當然,你應該繼續這種分化進一步打倒ImageData,`ChildData等

0

當你把它轉換爲ImageInfo你是正確的,像ImageData信息承載類不應該自動將自己保存到磁盤。涉及該操作的許多細節超出了任何類別的範圍,這些類別的任務主要是爲了表示數據。

對於這樣的類,提供將其轉換爲其他形式的方法是完全合理的,儘管它們即使需要某種通用支持。爲了從你的數據類中獲得磁盤存儲的細節,我會做這樣的事情......

您的所有數據類都會獲取可以將它們保存到給定(抽象)存儲位置的方法。您創建一個接口定義的存儲位置必須提供的服務有:

interface IMyStorage 
{ 
    ImageInfo SaveImage(ImageData); 
} 

class RootData 
{ 
    ... 
    RootInfo SaveTo(IMyStorage storage); 
} 

... 

class ImageData 
{ 
    ... 
    ImageInfo SaveTo(IMyStorage storage) 
    { 
     return storage.SaveImage(this); 
    } 
} 

然後你就可以做出IMyStorage的特定磁盤的實現,保存到磁盤,封裝的所有細節。