Instantiating Classes by Name with Factory Pattern

Instantiating classes by name with factory pattern

Here is a generic factory example implementation:

template<class Interface, class KeyT=std::string>
struct Factory {
typedef KeyT Key;
typedef std::auto_ptr<Interface> Type;
typedef Type (*Creator)();

bool define(Key const& key, Creator v) {
// Define key -> v relationship, return whether this is a new key.
return _registry.insert(typename Registry::value_type(key, v)).second;
}
Type create(Key const& key) {
typename Registry::const_iterator i = _registry.find(key);
if (i == _registry.end()) {
throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) +
": key not registered");
}
else return i->second();
}

template<class Base, class Actual>
static
std::auto_ptr<Base> create_func() {
return std::auto_ptr<Base>(new Actual());
}

private:
typedef std::map<Key, Creator> Registry;
Registry _registry;
};

This is not meant to be the best in every circumstance, but it is intended to be a first approximation and a more useful default than manually implementing the type of function stijn mentioned. How each hierarchy should register itself isn't mandated by Factory, but you may like the method gf mentioned (it's simple, clear, and very useful, and yes, this overcomes the inherent problems with macros in this case).

Here's a simple example of the factory:

struct Base {
typedef ::Factory<Base> Factory;
virtual ~Base() {}
virtual int answer() const = 0;

static Factory::Type create(Factory::Key const& name) {
return _factory.create(name);
}
template<class Derived>
static void define(Factory::Key const& name) {
bool new_key = _factory.define(name,
&Factory::template create_func<Base, Derived>);
if (not new_key) {
throw std::logic_error(std::string(__PRETTY_FUNCTION__) +
": name already registered");
}
}

private:
static Factory _factory;
};
Base::Factory Base::_factory;

struct A : Base {
virtual int answer() const { return 42; }
};

int main() {
Base::define<A>("A");
assert(Base::create("A")->answer() == 42);
return 0;
}

Factory Pattern to instantiate classes in a Factory class

First of all, your Create method doesn't actually create anything. It returns an instance that was already created. Every call to Create will return the same instance.

If that's what you want, fine, but if you want a new instance each time, may I make a suggestion? Instead of storing an object, store a function that returns a new object:

class Factory
{
Dictionary<string,Func<ICreate>> test = new Dictionary<string,Func<ICreate>>();

public Factory()
{
test.Add( "classA", () => new a() );
test.Add( "classB", () => new b() );
test.Add( "classC", () => new c() );
}

public ICreate Create(string toMatch)
{
var creationFunction = test[toMatch];
return creationFunction();
}
}

See how that works? The lambda expression () => new a() can be called like a function and will instantiate a new a with every call.

As for pattern matching, you can do something similar. We put a function in for the value; now let's put one in for the key. Instead of storing a string, we'll store a function that accepts a string and returns a Boolean. Then all we have to do is search for the first dictionary entry where executing the key returns true.

class Factory
{
Dictionary<Func<string,bool>,Func<ICreate>> _map = new Dictionary<Func<string,bool>, Func<ICreate>>();

public Factory()
{
_map.Add
(
a => a.Contains("classA"),
() => new a()
);
_map.Add
(
a => a.Contains("classB"),
() => new b()
);
_map.Add
(
a => a.Contains("classC"),
() => new c()
);
}

public ICreate Create(string toMatch)
{
var func = _map.Where( e => e.Key(toMatch) ).First().Value;
return func();
}
}

public class Program
{
static public void Main()
{
var f = new Factory();
var o = f.Create("c:\folder\subfolder\classA");
Console.WriteLine("You just created an instance of '{0}'.", o.GetType().Name);
}
}

Output:

You just created an instance of 'a'.

Code on DotNetFiddle

In this example we did pattern matching with Contains(), but since it is Func you can write any expression you want, using any of the string functions, regular expressions, you name it. You can also mix and match; for example, ,you could use a regular expression to identify a pattern that requires a ClassA, but you could use a regular == comparison to identify a pattern for ClassB. Also, we can change the LINQ function from First to Single if you want to ensure that whatever string was submitted matches one and only one pattern.

How to protect instantiation of concrete subclasses when using factory pattern?

I can give you hint on something you can try, though there can be some caveats:

  • create a separate factory class instead of base class.

  • make the constructor private in the the factory class

  • instantiate a dummy private object in the factory class

  • Let MinorEmployee and AdultEmployee 's only constructor accept object of factory class. Since object of factory can not exist out side the class due to private constructor, practically no one else should be able to instantiate those classes from outside.

  • Use the dummy object to pass on in your factory method.

Preventing a class instantiation in Scala using Factory Pattern

The conventional way to write a factory in Scala is to define an apply method on the companion object.

Here's an example using Either (because null is never/rarely used in Scala, and exceptions are ugly):

class A private (n: Int) {
override def toString = s"A($n)"
}

object A {
def apply(n: Int): Either[String, A] =
if (n < 5) Left("Too small")
else if (n > 10) Left("Too large")
else Right(new A(n))
}

A(4) // Left(Too small)
A(5) // Right(A(5))
A(11) // Left(Too large)

This is the essentially the same as the Java example you referenced. The A constructor is private, so the class can only be instantiated via the factory method.

Forcing the use of a factory object to instantiate a class

Some options:

  • reflection
  • register delegate that creates the class with factory class
  • configure your DI container to behave the way you need for that type of classes

Approximate code for delegate approach:

public class Factory {
private static Dictionary<Type, Func<Model>> creators;
public void AddCreator<T>(Func<T> creator) where T:Model
{
creators.Add(typeof(T), ()=> creator());
}

public static T Instance() where T : Model
{
return (T)(creators[typeof(T)] ());
}
}

Factory pattern in C#: How to ensure an object instance can only be created by a factory class?

Looks like you just want to run some business logic before creating the object - so why dont you just create a static method inside the "BusinessClass" that does all the dirty "myProperty" checking work, and make the constructor private?

public BusinessClass
{
public string MyProperty { get; private set; }

private BusinessClass()
{
}

private BusinessClass(string myProperty)
{
MyProperty = myProperty;
}

public static BusinessClass CreateObject(string myProperty)
{
// Perform some check on myProperty

if (/* all ok */)
return new BusinessClass(myProperty);

return null;
}
}

Calling it would be pretty straightforward:

BusinessClass objBusiness = BusinessClass.CreateObject(someProperty);

How to instantiate a child class using its parent factory in __construct

You try to use A_Factory::create_A() in the same way as you would use parent::__construct(). However, these are two completely different calls.

parent::__construct()

parent resolves to A. The current object $this is an instance of A (because every instance of B is also an instance of A due to inheritance). In this case, the call is not a static call, although the operator :: has been used ($this stays the same).

The following code works:

(given that foo is not private)

class B extends A
{
function __construct()
{
parent::__construct(new X, new Y, new Z);
echo $this->foo;
}
}

This one works too:

class B extends A
{
function __construct()
{
A::__construct(new X, new Y, new Z);
echo $this->foo;
}
}

Factory

A_Factory::createA() is a static call, because A_Factory is not in the inheritance tree of B. Also A_Factory creates and returns a new instance of A. So as soon as this has been called, you have two different objects: $this is still the unchanged B instance and you created a different instance of A without assigning it to any variable.

A possible approach is to move the factory method into A itself.

This will work:

class A
{
function __construct(X $x, Y $y, Z $z)
{
$this->foo = 'foo';
}
public static function create()
{
return new static (new X, new Y, new Z);
}
}

class B extends A
{
}

// Instantiating:
$a = A::create();
$b = B::create();

This makes use of late static binding with the static keyword. static resolves to the class name of the called class, so that it is A in A::create() and B in B::create().

Note the difference to self, which always resolves to the class where the method is declared (in this case it would be always A)



Related Topics



Leave a reply



Submit