- 1. Висновок
Обговорення. Фреймфорки є додатками (або підсистеми) з «місцями розширень» у них. Кожен такий фреймворк визначає інфраструктуру, надбудову та потік управління для своєї галузі діяльності, а клієнт фреймворку може здійснювати поведінку структури за умовчанням «як є», розширити виділені фрагменти структури або замінити вибрані фрагменти.
У шаблоні Factory Method розглядається поняття створення в контексті фреймворків. У цьому прикладі структура знає, КОЛИ має бути створено новий документ, а не ЯКИЙ це документ. «Заповнювач» Application::CreateDocument() був оголошений фреймворком, і клієнт повинен «заповнити пробіл» для свого конкретного документа(ів). Потім, коли клієнт запитує Application::NewDocument(), фреймворк згодом викликає метод 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(); }
Висновок
Application: ctor MyApplication: ctor Application: NewDocument() MyApplication: CreateDocument() MyDocument: Open() Application: NewDocument() MyApplication: CreateDocument() MyDocument: Open() Application: ReportDocs() foo bar
У метода NewDocument забыли указать возвращаемый тип (void). Я бы сделал бы сразу с проверочкой. И то что нет освобождение памяти, наверняка для обучающего материала это не хорошо.
И вот по освобождению памяти у меня вопрос - как лучше сделать освобождение памяти?
1. Можно сделать как я показал выше (реализовать диструктор ~Application()).
2. Так как память выделялась в MyApplication, то было бы не плохо если бы она и освобождала память, тогда нужно добавить метод DeleteDocument:
А диструктор переписать:
И для меня смысл фабричного метода, это когда ты через указатель базового класса работаешь с разными дочернеми классами.
Например в массиве: