From the problems encountered in the factory model
The following two types of problems can often be encountered in object-oriented system design:
1. In order to improve cohesion (cohesion) and loose coupling (coupling), we often abstract the common interfaces of some classes to form abstract base classes or interfaces. This allows us to point to the actual subclass implementation by declaring a pointer to the base class, which achieves polymorphic purposes. It's easy to see here a problem n many subclasses inherit from the abstract base class, and we have to write code such as newxxx every time we want to use the subclass. Here are two questions:
The client programmer must know the name of the actual subclass (when the system is complex, naming will be a difficult problem to deal with, in order to handle possible name conflicts, some naming may not be very readable and memorable, regardless of the different programmers strange personal preferences).
Extensibility and maintenance of programs are becoming more and more difficult.
2. There is also a situation where the parent class does not know exactly which specific subclass to instantiate. The meaning of this is: Suppose we use Class A in Class A b,b is an abstract parent class, in a does not know specifically to instantiate that a subclass of B, but in Class A subclass D is known. In a We have no way to directly use a statement similar to NEWXXX, because we don't know what XXX is.
The above two questions also lead to the two most important features of the factory model:
- Defines an interface for creating objects, encapsulating the creation of objects;
- Causes the work of the materialized classes to be deferred to subclasses.
Mode selection
We usually use the factory model to solve the two problems given above. In the first question, we often declare an interface to create an object and encapsulate the creation process of the object. The factory is similar to a factory (production object) in a real sense. In the second question, we need to provide an interface to object creation and provide its implementation in subclasses (because only in subclasses can you decide which class to instantiate).
The first case of the factory structure schematic diagram is:
Figure 1 The factory pattern is often used in system development, but this is not the greatest power of the factory model (because this can be solved by other means). The factory pattern not only provides an interface to create objects, but most importantly delays the instantiation of subclasses (the second problem), the following is the schematic diagram of a factory in this case:
The application of the key factory pattern in Figure 2 is not just to encapsulate the creation of objects, but to put the creation of objects into subclasses: The factory simply provides the interface for object creation, and its implementation will be carried out in the factory's subclass concrete factory. This is the difference between Figure 2 and Figure 1.
The implementation of the factory model
Complete code example: The Factory mode of implementation is relatively simple, here for the convenience of beginners learning and reference, will give a complete implementation code (all code in C + + implementation, and in VC 6.0 under test Run).
Code Snippets 1:product.h
Product.h
#ifndef _product_h_
#define _PRODUCT_H_
class product{public
:
virtual ~product () = 0;
Protected:
Product ();//Shielding Constructor
private:
};
Class concreteproduct:publicproduct{public
:
~concreteproduct ();
Concreteproduct ();
Protected:
private:
};
#endif//~_product_h_
Code Snippets 2:product.cpp
Product.cpp
#include "Product.h"
#include <iostream>
using namespace std;
Product::P roduct () {
}
product::~product () {
}
concreteproduct::concreteproduct () {
cout< < "Concreteproduct ..." <<endl;
}
Concreteproduct::~concreteproduct () {
}
Code Snippets 3:factory.h
Factory.h
#ifndef _factory_h_
#define _factory_h_
class Product;
Class factory{public
:
virtual ~factory () = 0;
Virtual product* createproduct () = 0;
Protected:
Factory ();
Private:
};
Class Concretefactory:public factory{public
:
~concretefactory ();
Concretefactory ();
product* createproduct ();
Protected:
private:
};
#endif//~_factory_h_
Code Snippets 4:factory.cpp
Factory.cpp
#include "Factory.h"
#include "Product.h"
#include <iostream>
using namespace STD;
Factory::factory () {
}
factory::~factory () {
}
concretefactory::concretefactory () {
cout< < "Concretefactory ..." <<endl;
}
Concretefactory::~concretefactory () {
}
product* concretefactory::createproduct () {return
new Concreteproduct ();
}
Code Snippets 5:main.cpp
Main.cpp
#include "Factory.h"
#include "Product.h"
#include <iostream>
using namespace STD;
int main (int argc,char* argv[]) {
factory* FAC = new Concretefactory ();
product* p = fac->createproduct ();
return 0;
}
Code Description: The example code gives the factory pattern to solve the problem that the parent class does not know exactly which specific subclass to instantiate, and to provide interface problems for creating objects, you can attach the corresponding creation operations such as create***product () to the factory. Please take part in the discussion details.
Discussion on the factory model
Factory models are widely used in practical development, and object-oriented systems often face the problem of object creation: There are too many classes to create. The factory-provided interface for creating objects encapsulates (the first feature), and it defers the instantiation of the class to subclasses (the second feature) solves the actual problem in part. A simple example is the author of the development of the VISUALCMCS system in the semantic analysis process, due to the syntax for each of the non-terminal constructs a class processing, so the process of creating a lot of objects, the use of Factory mode after the system readability and maintenance have become elegant many.
The factory model also brings at least the following two questions:
- If you provide a function body for the instantiation of each specific concreteproduct class, then we may have to add a method to the system to handle the new concreteproduct so that the factory's interface will never be closed (close). Of course we can do this through polymorphism by creating a subclass of a factory, but this is also the price of a new class.
- In the implementation we can pass a parameter to the factory method, that is, to plant methods () to pass a parameter to determine which specific Product is to be created (in fact, this is the author in Visualcmcs). Of course, you can also use the template to avoid 1 subclasses to create subclasses, the method is to use the specific Product class as a template parameter, the implementation is very simple.
As you can see, the factory pattern gives developers a good implementation strategy for creating objects, but the factory model is limited to a class of classes (that is, Product is a class, there is a common base class), and if we are going to provide an object-created interface for classes of different classes, it is necessary to use an abstract factory.