OO设计 - 多态 - 如何设计处理不同文件类型的流

时间:2010-03-16 22:27:48

标签: c++ oop polymorphism

我对高级OO实践的经验很少,我想把它设计成一个练习。我正在考虑实施以下内容,我问的是我是否正确地采用了这种方式。

我有一个类PImage,它保存原始数据和图像文件所需的一些信息。它的标题目前是这样的:

#include <boost/filesytem.hpp>
#include <vector>
namespace fs = boost::filesystem;
class PImage
{
  public:
    PImage(const fs::path& path, const unsigned char* buffer, int bufferLen) :
      path_(path), filesize_(bufferLen),
      data_(buffer, buffer + filesize_),
      width_(0), height_(0) {}
    const vector<char> data() const { return data_; }
    const char* rawData() const { return &data_[0]; }
    /*** other assorted accessors ***/
  private:
    fs::path path_;
    int filesize_;
    vector<char> data_;
    int width_;
    int height_;
}

我希望通过查看文件的标题来填充width_height_。琐碎/不优雅的解决方案是拥有大量凌乱的控制流程来识别图像文件的类型(.gif,.jpg,.png等),然后相应地解析标题。

我没有使用vector<char> data_,而是考虑让PImage使用继承自RawImageStream data_的类vector<char>。我计划支持的每种类型的文件都将从RawImageStream继承,例如RawGifStreamRawPngStream

每个RawXYZStream都会封装相应的标头解析函数,PImage只需执行类似height_ = data_.getHeight();的操作。

  1. 我是否通过正确思考?
  2. 如何为RawImageStream ctor中的data_创建正确的PImage子类?这是我可以使用对象工厂的地方吗?
  3. 我忘了什么?

3 个答案:

答案 0 :(得分:1)

是的,您可以按照描述的方式实现类层次结构。不过,我可能已经直接从PImage派生了PngImage,GifImage和JpegImage。然后PImage可以变得抽象:

class PImage
{
  virtual ~PImage {}
  virtual unsigned int getWidth() const = 0
  virtual unsigned int getHeight() const = 0
  ...
};

然后,每个具体的图像类型实现getWidth和getHeight。

然后可以由PImage工厂创建PImage类:

boost::shared_ptr<PImage> createImage(const fs::path& path);

在工厂中,您几乎打开文件,查看它具有的类型,并创建在构造函数中传递数据的具体图像类,最后将图像作为抽象PImage返回。

最后,我想补充一点,您不必过多担心您的设计,并在您发现您的设计无法满足您的需求时随时准备进行重构。通过反复试验,你会对你的问题的设计产生什么感觉!

答案 1 :(得分:1)

你应该看一下strategy pattern

答案 2 :(得分:0)

我会创建一个包含纯虚函数getHeight和getWidth()的AbstractImage类;

然后我会覆盖这些函数,例如GifImage,JpegImage和PngImage(它们都从AbstractImage继承)。

然后你做了什么工厂(工厂模式维基百科;)),它根据文件名为你创建正确的具体类。

所以这就像是

static AbstractImage* CreateImage(_fileName)
{
    switch(getExtension(_fileName))
    {
        case ".gif":
            return new GifImage(_fileName);
        case ".jpg":
            return new JpgedImage(_filename);
    }
}

因此,在此函数旁边,您不必担心您正在使用的实际派生类型。您可以使用AbstractImage提供的接口完成所有操作,并且多态性可以为您完成剩下的工作。