proper factory pattern in C++
Asked Answered
U

4

6

in C# you have to declare everything in a class so an example factory pattern could look like:

namespace MySpace {

public class CFactory
{
  public static CFactory Current()
  {
    static CFactory singleton;
    return singleton;
  }
  public CBase Create() { return null; }
}

}

in C++ you dont have this limitation.. So is it considered "bad practice" to have "factory" methods be global functions vs having them be a class?

example 1:

namespace MySpace {

// factory method
std::shared_ptr<CBase> CreateBase() { return NULL; }

}

example 2:

namespace MySpace {

// factory class
class CFactory
{
public:
  std::shared_ptr<CBase> CreateBase() { return NULL; }
};

// factory method exposing class
CFactory& GetFactory()
{
  static CFactory singleton;
  return singleton;
}

}

example 3:

namespace MySpace {

// factory class with no global function
class CFactory
{
public:
  std::shared_ptr<CBase> CreateBase() { return NULL; }

public:
  static CFactory& getFactory()
  {
     static CFactory singleton;
     return singleton;
  }
};

}

the std library uses a lot of global functions for "factory methods".. an example of this would be std::make_shared.

I have used both before and I am just not sure if one is considered "better" over the other

Unsettle answered 28/1, 2011 at 16:35 Comment(2)
I tend to put a static Foo *make() or similar inside the Foo base class. I really don't understand what's going on with the singleton in your second example...Lease
I added example 3 to remove the global function for the singleton. my focus is more on the factory pattern but others have been confused by example 2 as well.Unsettle
E
3

You can presume from its usage in the standard library that a namespaced global factory is not implicitly wrong. Nothing prevents it from being correct.

Your approach of wrapping the factory in a class is an organizational change. Organization itself is neither good nor bad. It can be done well or poorly.

You should be fine doing whichever approach feels comfortable for its context. I have also seen both approaches used many times and neither were particularly problematic.

Earleneearley answered 28/1, 2011 at 16:45 Comment(0)
G
1

I still recommend putting the functions into a class (and even make them virtual). It's very nice to be able to replace your factory for any number of reasons, and doing things that way will make this much easier.

In the standard library the factory functions largely exist because function template expansion can be based on the types of the arguments, but until C++17 you couldn't have template classes that create instances of the class based on the types fed to the constructor. So those factory functions are more properly thought of as non-member constructors than a factory. They always return an instance of a particular type for example.

In a 'true' factory, the factory can return any type that implements the specified interface or is derived from the specified type. True factories always return pointers or (in rare instances) references, but not actual instances.

Griggs answered 28/1, 2011 at 21:10 Comment(0)
P
0

Here is an example of a way to implement singleton in c++
This way you can avoid global.
Hope this helps.

 /* header file */

#ifndef EXAMPLE_H
#define EXAMPLE_H

class example
{
private:
    example(); // constructor
public:
    ~example(); // destructor
    static example *getExampleObject();
}
#endif

/* cpp file */
#include "example.h"

example *example::getExampleObject()
{
    static example *theInstance = NULL;
    if(theInstance == NULL)
    {
        theInstance = new example();
    }
    return theInstance;
}
Plucky answered 28/1, 2011 at 16:38 Comment(3)
yes the global function is not required in the second example. my focus was more on the factory pattern and not the singleton pattern :)Unsettle
Yeah, after reading your op again, i realized that you were talking about factory instead. my bad. Maybe someone will find it useful though. =PPlucky
I prefer: example& example::getExampleObject() { static example theInstance; return theInstance; } That way you will not have to worry about null pointersWendywendye
F
0

Free functions are fine in C++ and I would go with that route.

Somewhat unrelated: why are you returning a shared smart pointer from a factory? Is the ownership of the newly created object always going to be shared?

Fluoridate answered 28/1, 2011 at 21:5 Comment(1)
in the actually code, yes it is shared. :) sorry for the confusionUnsettle

© 2022 - 2024 — McMap. All rights reserved.