ОО Дизайн - полиморфизм - как проектировать для обработки потоков файлов разных типов - PullRequest
2 голосов
/ 17 марта 2010

У меня мало опыта в продвинутых ОО-методах, и я хочу разработать его как упражнение. Я думаю о реализации следующего и спрашиваю, правильно ли я поступаю.

У меня есть класс 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, например RawGifStream, RawPngStream.

Каждый RawXYZStream будет инкапсулировать соответствующие функции синтаксического анализа заголовка, а PImage будет делать только что-то вроде height_ = data_.getHeight();.

  1. Я правильно обдумываю это?
  2. Как мне создать правильный RawImageStream подкласс для data_, который будет в PImage ctor? Это где я мог бы использовать фабрику объектов?
  3. Что-нибудь, что я забыл?

Ответы [ 3 ]

1 голос
/ 17 марта 2010

Вы должны взглянуть на шаблон стратегии .

1 голос
/ 17 марта 2010

Да, вы можете реализовать иерархию классов так, как вы описываете. Тем не менее, я бы, вероятно, получил 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.

Наконец, я хотел бы добавить, что вам не нужно слишком беспокоиться о своем дизайне, и будьте готовы к рефакторингу позже, когда обнаружите, что ваш дизайн не соответствует вашим потребностям. Именно путем проб и ошибок у вас будет расти ощущение того, какой дизайн подходит для вашей проблемы!

0 голосов
/ 17 марта 2010

Я бы создал класс AbstractImage, содержащий чисто виртуальные функции getHeight и getWidth ();

Тогда я бы переопределил эти функции, например, в GifImage, JpegImage и PngImage (которые все наследуются от AbstractImage).

Тогда, что вы делаете фабрикой (фабричный шаблон wikipedia;)), которая создает правильный конкретный класс для вас в зависимости от имени файла.

Так что это будет что-то вроде

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

Так что помимо этой функции вам не нужно беспокоиться о фактическом производном типе, который вы используете. Вы можете делать все с помощью интерфейса, который обеспечивает AbstractImage, а полиморфизм сделает все остальное за вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...