Evgenii Legotckoi
Evgenii LegotckoiSept. 24, 2018, 8:23 a.m.

Example - Factory method in C++

Content

Discussion. Frameworks are applications (or subsystems) with "holes" in them. Each framework specifies the infrastructure, superstructure, and flow of control for its "domain", and the client of the framework may: exercise the framework's default behavior "as is", extend selected pieces of the framework, or replace selected pieces.

The Factory Method pattern addresses the notion of "creation" in the context of frameworks. In this example, the framework knows WHEN a new document should be created, not WHAT kind of Document to create. The "placeholder" Application::CreateDocument() has been declared by the framework, and the client is expected to "fill in the blank" for his/her specific document(s). Then, when the client asks for Application::NewDocument(), the framework will subsequently call the client's MyApplication::CreateDocument().


#include <iostream.h>

/* Abstract base class declared by framework */
class Document
{
  public:
    Document(char *fn)
    {
        strcpy(name, fn);
    }
    virtual void Open() = 0;
    virtual void Close() = 0;
    char *GetName()
    {
        return name;
    }
  private:
    char name[20];
};

/* Concrete derived class defined by client */
class MyDocument: public Document
{
  public:
    MyDocument(char *fn): Document(fn){}
    void Open()
    {
        cout << "   MyDocument: Open()" << endl;
    }
    void Close()
    {
        cout << "   MyDocument: Close()" << endl;
    }
};

/* Framework declaration */
class Application
{
  public:
    Application(): _index(0)
    {
        cout << "Application: ctor" << endl;
    }
    /* The client will call this "entry point" of the framework */
    NewDocument(char *name)
    {
        cout << "Application: NewDocument()" << endl;
        /* Framework calls the "hole" reserved for client customization */
        _docs[_index] = CreateDocument(name);
        _docs[_index++]->Open();
    }
    void OpenDocument(){}
    void ReportDocs();
    /* Framework declares a "hole" for the client to customize */
    virtual Document *CreateDocument(char*) = 0;
  private:
    int _index;
    /* Framework uses Document's base class */
    Document *_docs[10];
};

void Application::ReportDocs()
{
  cout << "Application: ReportDocs()" << endl;
  for (int i = 0; i < _index; i++)
    cout << "   " << _docs[i]->GetName() << endl;
}

/* Customization of framework defined by client */
class MyApplication: public Application
{
  public:
    MyApplication()
    {
        cout << "MyApplication: ctor" << endl;
    }
    /* Client defines Framework's "hole" */
    Document *CreateDocument(char *fn)
    {
        cout << "   MyApplication: CreateDocument()" << endl;
        return new MyDocument(fn);
    }
};

int main()
{
  /* Client's customization of the Framework */
  MyApplication myApp;

  myApp.NewDocument("foo");
  myApp.NewDocument("bar");
  myApp.ReportDocs();
}

Output

Application: ctor
MyApplication: ctor
Application: NewDocument()
   MyApplication: CreateDocument()
   MyDocument: Open()
Application: NewDocument()
   MyApplication: CreateDocument()
   MyDocument: Open()
Application: ReportDocs()
   foo
   bar
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

f
  • Aug. 9, 2019, 10:48 a.m.
  • (edited)

У метода NewDocument забыли указать возвращаемый тип (void). Я бы сделал бы сразу с проверочкой. И то что нет освобождение памяти, наверняка для обучающего материала это не хорошо.

    bool NewDocument(char *name)
    {
        if (_index >= 10) { return false; }
        cout << "Application: NewDocument()" << endl;
        /* Framework calls the "hole" reserved for client customization */

        _docs[_index] = CreateDocument(name);
        _docs[_index++]->Open();
        return true;
    }
    ~Application()
    {
        for (int i = _index - 1; i >= 0; --i) {
            delete _docs[i];
        }
    }

И вот по освобождению памяти у меня вопрос - как лучше сделать освобождение памяти?
1. Можно сделать как я показал выше (реализовать диструктор ~Application()).
2. Так как память выделялась в MyApplication, то было бы не плохо если бы она и освобождала память, тогда нужно добавить метод DeleteDocument:

    void DeleteDocument(Document *doc)
    {
        delete doc;
    }

А диструктор переписать:

    ~Application()
    {
        for (int i = _index - 1; i >= 0; --i) {
            DeleteDocument(_docs[i]);
        }
    }

И для меня смысл фабричного метода, это когда ты через указатель базового класса работаешь с разными дочернеми классами.
Например в массиве:

class Document {};

class Document1 : public Document {};

class Document2 : public Document {};

void main() {
    const int TYPE1 = 1;
    const int TYPE2 = 2;
    Document *m[10];
    for (int i = 0; i < 10; ++i) {
        int type;
        cin >> type;
        if (type == TYPE1) { m[i] = new Document1(); }
        else { m[i] = new Document2(); }
    }
    // some code
}

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Дмитрий

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:60points,
  • Rating points-1
Дмитрий

C++ - Тест 003. Условия и циклы

  • Result:92points,
  • Rating points8
d
  • dsfs
  • April 26, 2024, 11:56 a.m.

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:80points,
  • Rating points4
Last comments
k
kmssrFeb. 9, 2024, 2:43 a.m.
Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVADec. 25, 2023, 6:30 p.m.
Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJoDec. 25, 2023, 4:38 p.m.
Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
GvozdikDec. 19, 2023, 5:01 a.m.
Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Now discuss on the forum
G
George13May 7, 2024, 7:27 a.m.
добавить qlineseries в функции в функции: "GPlotter::addSeries(QString title, QVector &arr)" я вызываю метод setChart(...), я в конструктор передал адрес на QChartView элемент
BlinCT
BlinCTMay 5, 2024, 12:46 p.m.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
PS
Peter SonMay 4, 2024, 12:57 a.m.
Best Indian Food Restaurant In Cincinnati OH Ready to embark on a gastronomic journey like no other? Join us at App india restaurant and discover why we're renowned as the Best Indian Food Restaurant In Cincinnati OH . Whether y…
Evgenii Legotckoi
Evgenii LegotckoiMay 2, 2024, 9:07 p.m.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
IscanderChe
IscanderCheApril 30, 2024, 11:22 a.m.
Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

Follow us in social networks