Professional C__ - Marc Gregoire [487]
The first thing you’ll need is the hierarchy of cars. To keep this example simple, the Car class simply has an abstract method that returns a description of the car. Both Car subclasses are also defined in the following example:
#include class Car { public: virtual void info() = 0; }; class Ford : public Car { public: virtual void info() { std::cout << "Ford" << std::endl; } }; class Toyota : public Car { public: virtual void info() { std::cout << "Toyota" << std::endl; } }; Code snippet from CarFactory\Car.h The CarFactory base class is a bit more interesting. Each factory keeps track of the number of cars in production. When the public requestCar() method is called, the number of cars in production at the factory is increased by one, and calling the pure virtual createCar() method returns a new car. The idea is that individual factories will override createCar() to return the appropriate type of car. The CarFactory itself implements requestCar(), which takes care of updating the number of cars in production. CarFactory also provides a public method to query the number of cars being produced at each factory. The class definitions for the CarFactory class and subclasses are shown here: #include "Car.h" class CarFactory { public: CarFactory(); Car* requestCar(); int getNumCarsInProduction() const; protected: virtual Car* createCar() = 0; private: int mNumCarsInProduction; }; class FordFactory : public CarFactory { protected: virtual Car* createCar(); }; class ToyotaFactory : public CarFactory { protected: virtual Car* createCar(); }; Code snippet from CarFactory\CarFactory.h As you can see, the subclasses simply override createCar() to return the specific type of car that they produce. The implementation of the CarFactory hierarchy is as follows: #include "CarFactory.h" // Initialize the count to zero when the factory is created. CarFactory::CarFactory() : mNumCarsInProduction(0) {} // Increment the number of cars in production and return the new car. Car* CarFactory::requestCar() { mNumCarsInProduction++; return createCar(); } int CarFactory::getNumCarsInProduction() const { return mNumCarsInProduction; } Car* FordFactory::createCar() { return new Ford(); } Car* ToyotaFactory::createCar() { return new Toyota(); } Code snippet from CarFactory\CarFactory.cpp The implementation approach used in this example is called an abstract factory because the type of object created depends on which concrete subclass of the factory class is being used. A similar pattern can be implemented in a single class instead of a class hierarchy. In that case, a single create() method takes a type or string parameter from which it decides which object to create. For example, a CarFactory object would provide a buildCar() method that takes a string representing the type of car and constructs the appropriate type. The Microsoft MFC library uses such a concept. MFC has a function called CRuntimeClass::CreateObject() which accepts one parameter, a string which is the name of the class of which you want to create an object. The CreateObject() method is compiled into the MFC library in binary form, but still, due to the factory pattern, it is able to create objects of types unknown at the time the library was compiled. Factory methods are one way to implement virtual constructors: methods that create objects of different types. For example, the buildCar() method creates both Toyotas and Fords, depending on the concrete factory object on which it is called. Using a Factory The simplest way to use a factory is to instantiate it and to call the appropriate method, as in the following piece of code: ToyotaFactory myFactory; Car* myCar = myFactory.requestCar(); A more interesting example makes use of the virtual constructor idea to build a car in the factory that has the fewest cars in production. To