views:

1813

answers:

6

I've been looking at the example C++ Factory method pattern in Wikipedia http://en.wikipedia.org/wiki/Factory_method_pattern

and have a couple of questions:

1) Since the factory method is static, does that mean the newly created object won't go out of scope and have the destructor method called when the factory method exits?

2) Why return a pointer, as opposed to a reference? Is it strictly a matter of preference, or is the some important reason for this?

edit: The more I think about it, both the reference and the pointer returned will stay in scope because they are referenced outside of the method. Therefore, the destructor won't be called on either one. So it's a matter of preference. No?

edit2: I printed out the destructor call on the returned reference, and it doesn't print until the program exits. So, barring further feedback, I'm going to go with the reference for now. Just so I can use the "." operator on the returned object.

+3  A: 
  1. Static method is one that can be called without having an instance of the factory. That has nothing to deal wtih the lifetime of the newly created object. You could use a non-static method with the same success. The factory method usually doesn't need any data from an existing object of the same class and therefor doesn't need an existing instance and this is why factorey methods are usually static.

  2. You will use new to create the object that the factory will return. It's usual to return them by pointer. This shows explicitly that it's a new object ant the caller must take care of its lifetime.

sharptooth
+2  A: 

If you return a reference to an object that reference will become invalid when the method goes out of scope. This won't happen with a pointer, since the destructor isn't called.

It is true that static modifies when the value goes out of scope, but only if the variable is declared static, not if the method is declared static.

tomjen
You can do this: "return *(new Class);" this will give you a valid reference.
sharptooth
That makes sense. but then is there any situation where you would return a reference?
Jack BeNimble
It may be if your factory only operates on a pool of precreated objects.
sharptooth
@sharptooth Personally I feel dirty passing ownership through pointers
Ed
Isn't the original answer incorrect? I just tested it, and the returned reference is *not* destroyed, because the return value is specified in the method declaration - outside of the function.
Jack BeNimble
sharptooth
+6  A: 

I'm thinking there is a greater issue of understanding memory management. The factory method is allocating items on the heap (using new). Items on the heap never get automatically reclaimed (except by modern desktop OSs on process termination). The behavior you are describing is for items on the stack where they are reclaimed when you leave the local scope.

Ed
Ah, right, got it. Thanks :)
Jack BeNimble
+1  A: 
  1. No. Static method - is almost same as global function in class namesapce and with access to private static variables;
  2. Pointers usage is issue of createing objects in heap. They create object in heap for longer object lifetime than create-function scope;

EDIT:
I think wikipedia - is wrong in c++ example.
We have in exmaple - not same implementation as in class diagram or here (http://www.apwebco.com/gofpatterns/creational/FactoryMethod.html)

It will be better if you read about patterns from most trusted sources, e.g: Design Patterns: Elements of Reusable Object-Oriented Software.

bb
+1  A: 

Your Wiki link says wrong.

There shouldn't be any static method. You can consider Factory Method as Template Method pattern that creates Objects. This method doesn't receive any "Name" parameter and create all the time same type of object.

Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed. [GoF, p136]

In the following example Business::makeObject is the factory method

class ObjectBase
{
public:
    virtual void action() = 0;
    virtual ~ObjectBase(){};
};

class ObjectFirst : public ObjectBase
{
public:
    virtual void action(){ std::cout << "First"; }
};

class ObjectSecond : public ObjectBase
{
public:
    virtual void action(){ std::cout << "Second"; }
};


class Business
{
public:
    void SendReport()
    {
        std::auto_ptr< ObjectBase > object(makeObject());
        object->action();
    }
    virtual ~Business() { }
protected:
    virtual ObjectBase* makeObject() = 0;
};

class BusinessOne: public Business
{
public:
protected:
    virtual ObjectBase* makeObject()
    {
        return new ObjectFirst();
    }
};

class BusinessTwo: public Business
{
public:
protected:
    virtual ObjectBase* makeObject()
    {
        return new ObjectSecond();
    }
};

int main()
{
    std::auto_ptr<Business> business( new BusinessTwo() );
    business->SendReport();

    return 0;
}
Mykola Golubyev
He meant GOF patter "Factory method" - http://en.wikipedia.org/wiki/Factory_method_pattern
bb
I quoted text from the link.
Mykola Golubyev
A: 

The keyword static means different things on a method and on a variable. On a method as in the example it means that it is class global, and you need not have an instance of the class to call it.

To create a new object dynamically you need to use new, or 'a trick' is to assign a temporary object to a reference. assigning a temporary object to a point will not keep that object alive.

So you could do the following, but it is not normally done because you would often want to keep many things created from a factory, and then you would have to copy them rather than simply holding the pointer in a list.

class PizzaFactory {
public:
    static Pizza& create_pizza(const std::string& type) {
        if (type == "Ham and Mushroom")
            return HamAndMushroomPizza();
        else if (type == "Hawaiian")
            return HawaiianPizza();
        else
            return DeluxePizza();
    }
};

const Pizza &one = create_pizza(""); // by ref
Pizza two = create_pizza("");  // copied

EDIT Sorry mistake in code - added missing const to ref.

Normally, a temporary object lasts only until the end of the full expression in which it appears. However, C++ deliberately specifies that binding a temporary object to a reference to const on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself

Greg Domjan
This is undefined behaviour since you must not create references to temporary objects and you may especially not leak them out of scope. In any case, this code will crash (best case) or silently produce faulty behaviour.
Konrad Rudolph
Sorry but the standard says you can create references to temporary objects and that they will remain valid until the end of scope. At least in the version of the standard I saw...
Greg Domjan