[ fromfile: factory.xml id: factory ]
By using patterns to manage object creation, we gain flexibility that makes it possible to choose or change the kinds of objects created or used at runtime, and also to manage object deletion, especially in large software systems. Proper management of the creation of objects is an essential part of managing the separation between layers of code and ensuring the proper disposal of objects at destruction time.
In C++, a factory is a program component, generally a class, that is responsible for creating objects. The idea of a factory is to separate object creation from object usage.
A factory class generally has a function that obtains dynamic memory for the new object and returns a (base class) pointer to that object. This approach enables new derived types to be introduced without necessitating changes to the code that uses the factory.
This section will discuss several design patterns that use factories, and show examples of these design patterns.
When the responsibility for heap object creation is delegated to a virtual
function,
we call this a Factory method.
By making the factory method pure virtual
and writing concrete derived factory
classes, this becomes an abstract factory.
By imposing creation rules that prevent direct instantiation of a class, we can force clients to use Factory methods to create all instances. For example, there may be times when it is necessary to restrict the number of objects of a particular class that can exist at one time. In fact, making use of classes that can be instantiated exactly once is quite common.
We have already seen and worked with a singleton discussed in Section 8.3.
A Qt application that uses an event loop instantiates a QApplication
first, creates some other objects, and then calls QApplication::exec()
to start the event loop.
To refer to the object elsewhere in the program, you can make use of the qApp
macro,
which returns a pointer to the singleton QApplication.[94]
Section 16.1.3 discusses
singletons further.
Object Creation.
Consider three ways to create an instance of the QObject-derived
class Customer
:
Customer* c1 = new Customer(name);
QMetaObject meta = Customer::staticMetaObject; Customer* cust = qobject_cast<Customer*>(meta.newInstance());
Customer* cust = CustomerFactory::instance()->newCustomer(name);
In the first case, the class name is hard-coded in the constructor call. The object will be created in memory using the default heap storage. Hard-coded class names in client code can limit the reusability/flexibility of the code.
In the second case, QMetaObject::newInstance()
is called. This is an abstract factory, overridden in each QMetaObject
derived class, generated by moc
.
newInstance()
returns a QObject pointer to
a new instance of Customer
.
In the third case, a Customer
object is constructed indirectly using a specialized Factory method called CustomerFactory::newCustomer()
.
This interface might be more convenient to use than the Qt library, but it is simply a wrapper around another
factory.
Before QMetaObject::newInstance()
,[95] it was necessary to write a switch
statement to handle each supported class in a factory.
[94] QApplication is derived from
QCoreApplication. When
you #include <QApplication> you are
including the macro #define qApp (static_cast<QApplication*>(QCoreApplication::instance()))
QCoreApplication::instance()
returns a pointer to the already defined instance or null
, if no instance has
been created.
[95] Introduced in Qt 4.5
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |