SummaryThe Factory mode should also be one of the most widely used modes in modern programming languages. The Factory mode has many variants, which are implemented in various forms according to the actual situation. The most common possibility is the Abstract Factory mode and Factory Method mode proposed in GOF. This article is only based on the basic concept of the Facotry mode. Let's take a look at the implementation forms of common Factory modes mentioned by GOF, in other subsequent articles, we will discuss with you the Abstract Factory and Factory Method proposed by GOF. Factory mode, as its name implies, is the Factory that abstracts and encapsulates the instantiation action, and provides users with the interface as unified as possible to simplify the Object Instantiation process.
PurposeYou may ignore the logical process of Object Instantiation and call a unified interface to instantiate the object. At the same time, the coupling between the caller and the specific object is removed, so that the caller only relies on abstraction.
InstanceLet's look at the implementation of one of the simplest Factory modes. assume there is a set of objects ConcreteObjectA and ConcreteObjectB. Factory is responsible for Object Instantiation, class diagram:
The code is implemented as follows:
class AbstractObject {};class ConcreteObjectA : public AbstractObject {};class ConcreteObjectB : public AbstractObject {};class ConcreteObjectNULL : public AbstractObject {}; class Factory {public: AbstractObject* create_object(const string& type) { if (type == "A") { return new ConcreteObjectA; } else if type == "B") { return new ConcreteObjectB; } return new ConcreteObjectNULL; }};
You can use the unified create_object method to specify the type to instantiate the corresponding object:
Factory factory;AbstractObject* obj_A = factory.create_object("A");AbstractObject* obj_B = factory.create_object("B");
To make the Factory class easier to use, you can use the Singleton mode to wrap the Factory class. For the Singleton mode, see my previous article: [Introduction to design patterns] Singleton mode of creation patterns (do not abuse Singleton)
Although the implementation of this Factory mode is very simple, there is no technical content, but it is often used in many programs, because of the two words, simple! Some people may say that if every time you add an object, you need to modify the Factory class and add the corresponding object creation in it, isn't it against the Open-Close principle? For details about the Open-Close principle, refer to [design patterns] OCP-Open-Close principle of OO design principles. That's true. Let's slightly change the Factory implementation:
Construct a corresponding Factory for each specific object, create a map in the base class Factory, and maintain all the required Factory. each subclass Factory registers itself in the factory map in the constructor, the specific object is created by the corresponding Factory (override the do_create method). The Code is as follows:
class Factory {public: AbstractObject* create_object(const string& type) { std::map
::iterator it; it = factory_map.find(type); if (it != factory_map.end()) { return factory_map[type]->do_create(); } return factory_map["NULL"]->do_create(); } void register_factory(const string& type, Factory* factory) { factory_map[type] = factory; }private: virtual AbstractObject* do_create() = 0; static std::map
factory_map;};class FactoryA :public Factory{public: FactoryA() { register_factory("A", this); } virtual AbstractObject* do_create() { return new ConcreteObjectA; } };class FactoryB :public Factory{public: FactoryB() { register_factory("B", this); } virtual AbstractObject* do_create() { return new ConcreteObjectB; } };class FactoryNULL :public Factory{public: FactoryNULL() { register_factory("NULL", this); } virtual AbstractObject* do_create() { return new ConcreteObjectNULL; } };
When using this function, you must first define all Factory objects, and then use the create_object method of the Factory to create the corresponding objects:
FactoryA factory_A; FactoryB factory_ B; FactoryNULL factory_NULL; // the definition of the above object is generally defined as a global object in the cpp file implemented by the corresponding Factory class.
Note that Singleton is generally used to wrap the Factory, which is more convenient to use. To simplify the implementation process, Singleton is not used here.
Factory factory;AbstractObject* obj_A = factory.create_object("A");AbstractObject* obj_B = factory.create_object("B");
Compared with the first implementation, to add a specific object ConcreteObjectC, you no longer need to modify the Factory class itself. You only need to add FactoryC and define the FactoryC type object factory_C in the code, meets the requirements of the open and closed principle.
I once described that the second implementation is to change the implementation of the first Factory, but not the improvement. Because the two implementations have their own advantages and disadvantages, although the second implementation is more ideal from the perspective of OO design, it also brings the following problems: 1. each Factory must be instantiated before use. 2. implementation becomes more complex 3. no more objects need to add a new Factory class. Of course, when using Java or other languages for implementation, some difficulties in C ++ implementation can be avoided, making the implementation simpler.
ApplicationThe Factory mode is one of the most widely used design patterns. It can be said that a slightly larger program is enriched with various forms of Factory. When using C ++ to implement the current situation, you need to pay attention to some additional issues, for example, how to destroy an object and manage the object lifecycle.