2009-01-24 95 views
2

我有一個要求以各種格式保存圖像文件。 格式列表可能會經常更改,所以我希望這種保存會非常可擴展。 此外,保存可以發生在許多地方(硬盤,FTP,HTTP等)。保存位置的列表也將經常改變。設計模式適合任務

我想我會使用基底圖像類和很多派生類每種格式:

ImageBase {} 
JpegImage : ImageBase {} 
TiffImage : ImageBase{} 

和處理每個子類中適當地保存到格式。 這是一個很好的設計desicion?

另外,我怎樣才能附加一個可擴展的保存位置機制(Ftp,文件共享等)?

我想是這樣的:

var image=ImageBase.GetImageFromDisk(path); 
//some casting to subclass maybe?? 
var tiffImage=image as TiffImage; 
tiffImage.Location=new FtpLocation();//not sure if this is a good idea 
tiffImage.Save(); 

這裏的問題是,具體的影像實現不應該知道或關心的保存位置。 在圖像子類上調用Save();時,我想將作品委託給某個類,如FtpLocation

請指教如何把碎片放在一起。

謝謝。

瓦倫丁。

+0

女士們是不是可以回答這個問題? ;) – 2009-01-24 08:26:35

回答

5

首先我會在你的圖像上實現流。通過這種方式,您可以從流中創建構造函數,併爲您的任何「圖像」子類創建流。

此外,我將創建「節約型」的基礎設施,以簡單地接受流,並把它們寫下來到你合適的技術(FTP,文件等)

你最終可擴展的圖像(如果你能得到這樣一個流它可以做很多很多事情),你最終得到一個可擴展的節約基礎設施(任何可以去一個流的任何東西都可以保存)

編輯:個人,保存方法數據類型對象聽起來像是在錯誤的地方,但不知道你的整個系統,我不能肯定地說。只是我的2c。

1

在我看來,具體的類應該只處理原始數據;這可能是編寫一個本地文件(然後由基本代碼處理)或流。

例如,可能是這樣的:

public void Save() 
{ 
    // TODO: add any language-specific constructs like "using", etc 
    Stream stream = Location.OpenWrite(); 
    Save(stream); 
    stream.Close(); 
} 

protected abstract void Save(Stream stream); 

所以Location負責提供流(這可能是一個內存流,傳輸流,一個臨時文件流,等),以及可選做當該流關閉時(通過裝飾器模式封裝內部流)進行額外的工作。所有的子類都會寫入一個流。

加載有點棘手,因爲基類必須假設(給出你建議的來自基類的靜態加載)查看流來識別類型。但最終,你可以有類似的東西:

public static ImageBase Load(Location location) 
{ 
    // TODO: add any language-specific constructs like "using", etc 
    Stream stream = location.OpenRead(); 
    // TODO: wrap in a buffered/seekable stream so we can peek 
    // TODO: parse headers and resolve image type 
    ImageBase image = ... 
    image.Location = location; 
    stream.Position = 0; // rewind buffered/seekable stream 
    // (don't use Load() since we have already opened the stream) 
    image.Load(stream); 
    stream.Close(); 
    return image; 
} 
protected abstract void Load(Stream stream); 
public void Load() 
{ 
    // TODO: add any language-specific constructs like "using", etc 
    Stream stream = Location.OpenRead(); 
    Load(stream); // don't need to buffer if loading from subclass 
    stream.Close(); 
} 
0

在基址類實現保存(),而不是在派生類。

0

我認爲保存/加載子圖像本身不是一個正確的想法,因爲你不會有實例來調用加載。內存中的圖像與原始格式完全無關 - 例如,打開jpg然後將其保存爲png是絕對有可能的。

我會做下列方式:

Image 

ImageFormat { Save(Image, Stream); Image Load(Stream); } 
JpegFormat : ImageFormat {} 
TiffFormat : ImageFormat {} 

現在的位置,你只需要提供一種方式來獲得一個流閱讀和寫作流。

1

我會採取稍微不同的方式。 (語法就是Java。)

public class Image { 
    public void load(byte[] imageData); 
    public byte[] getImageData(); 
} 

public class JpegImage extends Image { 
    public void load(byte[] imageData) { 
     /* decode image data. */ 
    } 

    public byte[] getImageData() { 
     /* encode and return the JPG data. */ 
    } 
} 

public class Location { 
    public Image loadImage(String uri); 
    public void saveImage(Image image); 
} 

public class HttpLocation extends Location { 
    public Image loadImage(String uri) { 
     byte[] = getData(uri); 
     if (type == JPEG) { 
      return new JpegImage().load(byte); 
     } else if (type == PNG) { 
      return new PngImage().load(byte); 
     } 
    } 
    public void saveImage(Image image) { 
     byte[] imageData = image.getImageData(); 
     /* upload. */ 
    } 
} 

從Web服務器的內容類型的Image類的映射也可能發生在外景基地類更可重用的方式(或者完全不同的輔助類),但是這是關於如何我會做。

0

對於圖像,我會繼承。對於加載/保存部分,我會使用策略設計模式,以便每個圖像都可以有一個加載算法和一個SavingAlgorithm。通過這種方式,您可以改變加載和保存過程,而無需製作Image類的加載和保存方法。