2009-01-24 78 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类的加载和保存方法。