Factory Method Implementation - C++

Factory pattern implementation using ANSI C

C have function pointers and structs. So you can implement classes in C.

something like this should give you a clue.

void class1_foo() {}
void class2_foo() {}

struct polyclass
{
void (*foo)();
};

polyclass make_class1() { polyclass result; result.foo = class1_foo; return result; }

How to implement the factory method pattern in C++ correctly

First of all, there are cases when
object construction is a task complex
enough to justify its extraction to
another class.

I believe this point is incorrect. The complexity doesn't really matter. The relevance is what does. If an object can be constructed in one step (not like in the builder pattern), the constructor is the right place to do it. If you really need another class to perform the job, then it should be a helper class that is used from the constructor anyway.

Vec2(float x, float y);
Vec2(float angle, float magnitude); // not a valid overload!

There is an easy workaround for this:

struct Cartesian {
inline Cartesian(float x, float y): x(x), y(y) {}
float x, y;
};
struct Polar {
inline Polar(float angle, float magnitude): angle(angle), magnitude(magnitude) {}
float angle, magnitude;
};
Vec2(const Cartesian &cartesian);
Vec2(const Polar &polar);

The only disadvantage is that it looks a bit verbose:

Vec2 v2(Vec2::Cartesian(3.0f, 4.0f));

But the good thing is that you can immediately see what coordinate type you're using, and at the same time you don't have to worry about copying. If you want copying, and it's expensive (as proven by profiling, of course), you may wish to use something like Qt's shared classes to avoid copying overhead.

As for the allocation type, the main reason to use the factory pattern is usually polymorphism. Constructors can't be virtual, and even if they could, it wouldn't make much sense. When using static or stack allocation, you can't create objects in a polymorphic way because the compiler needs to know the exact size. So it works only with pointers and references. And returning a reference from a factory doesn't work too, because while an object technically can be deleted by reference, it could be rather confusing and bug-prone, see Is the practice of returning a C++ reference variable, evil? for example. So pointers are the only thing that's left, and that includes smart pointers too. In other words, factories are most useful when used with dynamic allocation, so you can do things like this:

class Abstract {
public:
virtual void do() = 0;
};

class Factory {
public:
Abstract *create();
};

Factory f;
Abstract *a = f.create();
a->do();

In other cases, factories just help to solve minor problems like those with overloads you have mentioned. It would be nice if it was possible to use them in a uniform way, but it doesn't hurt much that it is probably impossible.

Factory method C++ implementation

  1. You don't need to make instance BreadFactory. Just use static method.

    class BreadFactory
    {
    public:
    static Bread* makeBread( QString type )
    {
    ...
    }
    };

    //in main
    Bread *breadType = BreadFactory::makeBread( "White Bread");
    breadType->print();
  2. Use c++11 override keyword, for clarity.

    class WhiteBread : public Bread
    {
    public:
    void print() override{
    ...
  3. Use c++11 unique_ptr among smart pointer.

    static unique_ptr<Bread> makeBread( QString type ) {
    if ( type == "White bread" )
    return std::make_unique<WhiteBread>();
    else if ( type == "Brown bread" )
    return std::make_unique<BrownBread>();
    else
    return nullptr;
    }
  4. Use virtual destructor.

    class Bread
    {
    public:
    virtual void print() = 0;
    virtual ~Bread() {};
    };

Factory method implementation - C++

In the example you posted, neither a factory or a template approach makes sense to me.
My solution involves a data member in the Pen class.

class Pen {
public:
Pen() : m_color(0,0,0,0) /* the default colour is black */
{
}

Pen(const Color& c) : m_color(c)
{
}

Pen(const Pen& other) : m_color(other.color())
{
}

virtual void Draw()
{
cout << "Drawing with a pen of color " << m_color.hex();
}
void setColor(const Color& c) { m_color = c; }
const Color& color() const { return m_color; }
private:
Color m_color;
};

class Color {
public:
Color(int r, int g, int b, int a = 0) :
m_red(r), m_green(g), m_blue(other.blue()), m_alpha(a)
{
}

Color(const Color& other) :
m_red(other.red()), m_green(other.green()),
m_blue(other.blue()), m_alpha(other.alpha())
{
}

int red() const { return m_red; }
int green() const { return m_green; }
int blue() const { return m_blue; }
int alpha() const { return m_alpha; }

std::string hex() const
{
std::ostringstream os;
char buf[3];
os << "#";

sprintf(buf, "%2X", red());
os << buf;

sprintf(buf, "%2X", green());
os << buf;

sprintf(buf, "%2X", blue());
os << buf;

sprintf(buf, "%2X", alpha());
os << buf;

return os.str();
}

private:
int m_red;
int m_green;
int m_blue;
int m_alpha;
}

Of course, the color class would have to be adjusted to the drawing API you use -- and perhaps be way more advanced than this one (different color spaces, etc).

Why not templates?

The reason it does not make sense to use templates, is that (presumably) the only difference between the different drawing operations is the color variable. So, by using templates (or manually declaring different classes, as you did), you will duplicate similar code. This will make your program large, and slow it down.

So, the draw function should either take the color as an argument, or (as in my example) have the color as a class data member.

Factory Method C++

Here is a corrected sample (as far as I understood what you want to achieved). See code comments clarifying why stuff where changed. A lot more would be needed to make the core more robust (eg using ObjectType inside the base class)

#include <iostream>

enum ObjectType {
FO_Object2 = 2,
FO_Object3 = 3
};

class Object {
public:
int ID; // ID must be public so that inherited class can access it. Otherwise create getter for ID
Object(int id) : ID(id) {};
Object(const Object&) = delete;

virtual void printObject() = 0;
static Object* make_object(int id);
};

class Object2: public Object
{
public:
Object2():Object(2) {}; // specifically instanciate a base class whose id is 2
void printObject() {
std::cout << "ID = "<< ID << std::endl;
}
};

class Object3 : public Object
{

public:
Object3():Object(3) {}; // specifically instanciate a base class whose id is 3
void printObject() {
std::cout << "ID = "<< ID << std::endl;
}
};

//Factory Method to create objects
Object* Object::make_object(int id)
{
switch (id)
{
case FO_Object2: return new Object2();
case FO_Object3: return new Object3();
default:
return NULL;
}
}

class object_factory
{
public:
object_factory()
{
ObjectType id = FO_Object3;
pObject = Object::make_object(id);
}
~object_factory()
{
if (pObject) {
delete[] pObject;
pObject = NULL;
}
}
Object* getFactory() {
return pObject;
}
private:
Object* pObject;
};

int main()
{
object_factory* pFactory = new object_factory();
Object* pObject = pFactory->getFactory();
pObject->printObject();

return 0;
}

factory method design pattern

Your Creator class is the factory. Let's call it ProductFactory, in order to make the example more explicit.

(i am assuming you are using C++)

class Book : public Product
{
};

class Computer : public Product
{
};

class ProductFactory
{
public:
virtual Product* Make(int type)
{
switch (type)
{
case 0:
return new Book();
case 1:
return new Computer();
[...]
}
}
}

Call it like this:

ProductFactory factory = ....;
Product* p1 = factory.Make(0); // p1 is a Book*
Product* p2 = factory.Make(1); // p2 is a Computer*
// remember to delete p1 and p2

So, to answer your question:

What does it have to do with subclasses? And what am I supposed to use
subclasses for?

What the definition for factory pattern is saying is that the factory defines a common API for creating instances of a certain type (normally an interface or abstract class), but the real type of the implementations returned (thus the subclass reference) is the responsibility of the factory. In the example, the factory returns Product instances, for which Book and Computer are valid subclasses.

There are other idioms for factory, like having an API for the factory and the concrete implementations of the factory do not accept a type like in my example, but they are coupled with the type of instances returned, like this:

class ProductFactory
{
public:
virtual Product* Make() = 0;
}

class BookProductFactory : public ProductFactory
{
public:
virtual Product* Make()
{
return new Book();
}
}

In this class BookProductFactory always returns Book instances.

ProductFactory* factory = new BookProductFactory();
Product* p1 = factory->Make(); // p1 is a Book
delete p1;
delete factory;

To make it clear, since there seems to be a bit of confusion between Abstract Factory and Factory method design patterns, let's see a concrete example:

Using Abstract Factory

class ProductFactory {
protected:
virtual Product* MakeBook() = 0;
virtual Product* MakeComputer() = 0;
}

class Store {
public:
Gift* MakeGift(ProductFactory* factory) {
Product* p1 = factory->MakeBook();
Product* p2 = factory->MakeComputer();
return new Gift(p1, p2);
}
}

class StoreProductFactory : public ProductFactory {
protected:
virtual Product* MakeBook() { return new Book(); }
virtual Product* MakeComputer() { return new Computer(); }
}

class FreeBooksStoreProductFactory : public StoreProductFactory {
protected:
virtual Product* MakeBook() {
Book* b = new FreeBook(); // a FreeBook is a Book with price 0
return b;
}
}

That is used like this:

Store store;
ProductFactory* factory = new FreeBooksStoreProductFactory();
Gift* gift = factory->MakeGift(factory);
// gift has a FreeBook (Book with price 0) and a Computer
delete gift;
delete factory;

Using Factory method

class Store {
public:
Gift* MakeGift() {
Product* p1 = MakeBook();
Product* p2 = MakeComputer();
return new Gift(p1, p2);
}

protected:
virtual Product* MakeBook() {
return new Book();
}

virtual Product* MakeComputer() {
return new Computer();
}
}

class FreeBooksStore : public Store {
protected:
virtual Product* MakeBook() {
Book* b = new FreeBook(); // a FreeBook is a Book with price 0
return b;
}
}

That is used like this:

Store* store = new FreeBooksStore();
Gift* gift = store->MakeGift();
// gift has a FreeBook (Book with price 0) and a Computer
delete gift;
delete store;

When you use a type discriminator like I did in the original example, we are using parametized factory methods - a method that knows how to create different kind of objects. But that can appear in either an Abstract Factory or Factory Method pattern. A brief trick: if you are extending the factory class you are using Abstract Factory. If you extending the class with the creation methods, then you are using Factory Methods.

Having trouble with inheritance in implementation of C++ factory method

There are a few things to consider:

  1. The reason your code won't compile is due to its structure. You can't (or shouldn't) have factory.h include truckfactory.h, which then includes factory.h. The circular dependency will cause you problems. The normal way of handling this is to forward declare truck_factory like this:
 #ifndef FACTORY_H
#define FACTORY_H

#include <iostream>

class truck_factory;

class factory{

public:
std::string typeOfCar;
factory(){}

virtual void identifyCar(){
std::cout << "This car is a " + typeOfCar << std::endl;
}

truckfactory* createTruck(); //Note definition must be in c++ file
};
#endif

  1. Conceptually your factory should build objects, not other factories. For example, you might have a class factory which knows how to build trucks, car, motorbikes etc. To do this you would want to define a vehicle class and then a factory which can build the correct class based on the type passed in. Something like:
class Vehicle {
public:
virtual std::string typeOfCar() const = 0;
void identifyCar() {
std::cout << "This car is a " + typeOfCar << std::endl;
}
};

class Factory {
public:
Vehicle* create_vehicle(const std::string& type); // need to somehow specify what type you want to create.
};

class Truck : public Vehicle {
virtual std::string typeOfCar() const { return "truck"; }
};

The create_vehicle function would need to be defined in a cpp file to return various vehicle types.



Related Topics



Leave a reply



Submit