как создавать разные объекты с помощью фабричных методов

0

я прошел шаблон заводского дизайна и получил некоторые сомнения, код, который я видел, где в register функции,

они сохраняют объект на map (при регистрации, создании объектов в первый раз и хранении их в классе контейнера), когда нам нужен объект, который мы должны запрашивать у фабрики (Factory::getObject("Rectangle")), это прямоугольник создается и сохраняется на карте уже во время регистрации, и этот объект возвращается, когда я getObject("Rectangle")).

Я сомневаюсь, что каждый раз, когда я получаю только один объект, если я хочу создать 10 разных объектов для прямоугольника,

Как я могу создать 10 объектов diff этого прямоугольника?

Заранее спасибо.

RangeRingsFactory::RangeRingsFactory()
{
    Register("Big", &Picture::Create);            //picure & picyureInPicture inherited from IRangeRings 
    Register("Small", &PictureInPicture::Create);
}

RangeRingsFactory *RangeRingsFactory::Get()
{
    static RangeRingsFactory instance;
    return &instance;
}
void RangeRingsFactory::Register(const string &Name, CreateRRFn pfnCreate)
{
    map1[Name] = pfnCreate;
}

IRangeRings *RangeRingsFactory::CreateRR(const string &Name)
{
     FactoryMap::iterator it = map1.find(Name);
            if( it != map1.end() )
                   return it->second();
            return NULL;

}

картина:

Picture::Picture():IRangeRings()
{
    setRangeScale(QRect(-200,-200,400,400));
}
IRangeRings *Picture::Create()
{
    return new Picture();
}

главный:

MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
    string Name1 = "Big";
    IRangeRings *p1 = RangeRingsFactory::Get()->CreateRR(Name1);
    string Name2 = "Small";
    IRangeRings *p2 = RangeRingsFactory::Get()->CreateRR(Name2);

    outerLayout = new QHBoxLayout;

    outerLayout->addWidget(p1);
    outerLayout->addWidget(p2);
    this->setLayout(this->outerLayout);
}
  • 0
    Я не думаю, что вы читали только о фабричном методе. Может быть, это сочетание двух или более шаблонов дизайна ... sourcemaking.com/design_patterns/factory_method эта ссылка может вам помочь ...
  • 0
    Я думаю, что вы просто получаете объект шаблона с помощью Factory::getObject . Вы должны создать новый объект им. Можете ли вы добавить ссылку на factory design pattern который вы упомянули в квесте.
Показать ещё 2 комментария
Теги:

3 ответа

0

Решение A

Он будет иметь другой прямоугольник в IRangeRings, если вы установите другой прямоугольник при создании IRangeRings.

Измените эти функции:

CreateRRFn()
IRangeRings *RangeRingsFactory::CreateRR(const string &Name)
IRangeRings *Picture::Create()

Для того, чтобы:

CreateRRFn(QRect rect)
IRangeRings *RangeRingsFactory::CreateRR(const string &Name, const QRect &rect)
IRangeRings *Picture::Create(const QRect &rect)

Затем используйте экземпляр RangeRingsFactory для создания новых IRangeRings следующим образом:

IRangeRings *p1 = RangeRingsFactory::Get()->CreateRR("Big", QRect(0, 0, 100, 100));

Решение B

Также вы можете добавить новую чистую virtual функцию в IRangeRings (я думаю, что IRangeRings - это класс интерфейса), я назвал его как ToSetRangeScale. И Picture и PictureInPicture должны реализовать это:

void Picture::ToSetRangeScale(const QRect &rect) { setRangeScale(rect); }
void PictureInPicture::ToSetRangeScale(const QRect &rect) { setRangeScale(rect); }

Затем вызовите ToSetRangeScale чтобы установить rect после создания объекта Picture или PictureInPicture:

IRangeRings *p1 = RangeRingsFactory::Get()->CreateRR("Big");
p1->ToSetRangeScale(QRect(0, 0, 100, 100));

В конце концов

В RangeRingsFactory хранятся некоторые указатели функции Create. Эта же функция может создать другой объект, который имеет тот же класс. Разная функция может создавать разные объекты с разными классами. Если вы хотите изменить свойство нового объекта, вы можете установить его свойство при создании объекта или после создания объекта новым методом.

0

На фабрике хранится карта строк для "функций создания". В его конструкторе он регистрирует два из них: "Большой" соответствует Picture::Create и "Small" соответствует PictureInPicture::Create.

Метод CreateRR ищет данное Name, вызывает соответствующую функцию создания и возвращает его результат.

Пока оба Picture::Create и PictureInPicture::Create производят новые объекты, вы получаете новый объект каждый раз, когда вы вызываете CreateRR.

Так что на самом деле у вас есть...

  • две заводские функции - Picture::Create и PictureInPicture::Create - каждый из которых всегда создает один и тот же тип объекта

  • один заводский класс - RangeRingsFactory - который скрывает от вас определенные типы (Picture и PictureInPicture), поэтому вы можете просто попросить один по имени ("Большой" или "Малый"), не зная и не заботясь о конкретном типе объекта, который создается.

0

Похоже, вы думаете о комбинации "прототипов" и "фабричных" моделей. Фабрика позволяет клиентам "регистрировать" экземпляры прототипов, которые могут быть подклассами некоторой общей базы. Затем метод getObject создает копию запрошенного прототипа.

Я сделал быстрый Google для "прототипа шаблона c++"... Вот два из многих результатов:

http://en.wikibooks.org/wiki/C%2B%2B_Programming/Code/Design_Patterns#Prototype

http://www.codeproject.com/Articles/185348/Prototype-Design-Pattern-2

Вот простой пример с использованием shape базового класса и двух подклассов rectangle и circle. Эти классы мало что делают, но они имеют минимальную структуру для иллюстрации шаблона.

(Предупреждение: я на самом деле не компилировал это, так что дайте мне перерыв, если я сделаю простые ошибки!)

#include <map>

// Abstract base class for all shapes
class shape
{
public:
  virtual ~shape() {}
  virtual shape* clone() const = 0;
};

// Concrete subclass of shape
class rectangle : public shape
{
public:
  virtual shape* clone() const override
  {
    return new rectangle( *this );
  }
};

// Concrete subclass of shape
class circle : public shape
{
public:
  virtual shape* clone() const override
  {
    return new circle( *this );
  }
};

class Factory
{
public:
  // Add the given prototype object to the factory
  void register( std::string name, shape* proto )
  {
    protos[name] = proto;
  }

  // Get a copy of the prototype with the given name
  shape* getObject( std::string const& name ) const
  {
    // Warning: This will throw if name is not found!
    return protos[name]->clone();
  }

private:
  // Warning: This will leak unless cleaned up in the destructor!
  std::map<std::string, shape*> protos;
};

int main()
{
  Factory fact;
  fact.register( "rectangle", new rectangle() );
  fact.register( "circle", new circle() );

  // These will be separate copies of the original prototype
  shape* rect1 = fact.getObject( "rectangle" );
  shape* rect2 = fact.getObject( "rectangle" );

  // Don't leak!
  delete rect1;
  delete rect2;
}

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню