Best way to build a factory
Asked Answered
H

6

6

I have been reading about Factory pattern a lot lately. I am trying to figure out the best way to implement it. In the book C # Agile Principles patterns and practice the recommendation is to create the Factory like this:

public class ShapeFactoryImplementation : ShapeFactory {
    public Shape Make(string name) {
        if (name.Equals("Circle"))
            return new Circle();
        else if (name.Equals("Square"))
            return new Square();
        else
            throw new Exception("ShapeFactory cannot create: {0}", name);
        }
    }

Rather than...

public class ShapeFactoryImplementation : ShapeFactory {
    public Shape MakeCircle() {
        return new Circle();
    }

    public Shape MakeSquare() {
        return new Square();
    }
}

Please tell me what are your thoughts? Or maybe there is a better way to implement the factory pattern?

Hazardous answered 31/8, 2011 at 11:28 Comment(2)
The second version is kind of goofy anyway. You're naming methods explicitly (e.g. MakeSquare, MakeCircle, ...) but then you're returning an abstract type - Shape. Maintenance issues aside, it has a dirty feel to it already.Buhler
what kind of factory do you use ?Hazardous
F
2

The main point of the factory pattern is to de-couple the client from the creation of objects.

In your second example, the client has hard-coded the shape to create, such as MakeCircle, and therefore tightly couples the object creation and the client.

Faitour answered 31/8, 2011 at 11:34 Comment(5)
may i ask what way do you use ?Hazardous
If I was using a Factory Pattern I'd use something like the first example. However, I find dependency injection more useful in most cases.Faitour
OK, that sound fair. so what your saying is rather then using a factory pattern you prefer to use DI in most cases ?Hazardous
It depends on the situation, but yes.Faitour
You could use an Interface of type IFactoriedObject and have your factoried classes inherit that. You know what type of factory you're creating so you should be able to do it directly without having to go through logical if/then/select/case/norris statements.Italian
D
3

In the first version the interface of ShapeFactoryImplementation remains the same. In the second every time you add a new method you have a new interface.

Dinger answered 31/8, 2011 at 11:33 Comment(0)
C
3

In my opinion both of these implementations break at least couple of rules, Single Responsibility Principle (ok, you could argue that it's responsible for creation, but IMO that's too broad responsibility) and Open/Closed Principle (every time you add a shape you need to change the class). Not to mention the fact, that the first implementation doesn't allow you to provide parameters for constructors. The way I tend to solve this is to use the following approach:

    public struct ShapeCreationSettings
    {
        public Predicate<string> Predicate;
        public Func<IShapeCreationParams, Shape> Creator;
    }

    public interface IShapeCreationParams
    {}

    public struct CircleCreationParams : IShapeCreationParams
    {
        public CircleCreationParams(int r) : this()
        {
            R = r;
        }

        public int R  { get; private set; }
    }

    public struct SquareCreationParams : IShapeCreationParams
    {
        public SquareCreationParams(int a) : this()
        {
            A = a;
        }

        public int A { get; private set; }

    }

    public class ShapeFactory : IShapeFactory
    {
        protected static List<ShapeCreationSettings> settings = new List<ShapeCreationSettings>();

        static ShapeFactory()
        {
            settings.Add(new ShapeCreationSettings
            {
                Predicate = t => t.Equals("Circle"),
                Creator = p => new Circle(((CircleCreationParams) p).R)
            });
            settings.Add(new ShapeCreationSettings
            {
                Predicate = t => t.Equals("Square"),
                Creator = p => new Square(((SquareCreationParams)p).A)
            });
        }

        public Shape Create(string name, IShapeCreationParams p)
        {
            return settings.FirstOrDefault(s => s.Predicate(name)).Creator(p);
        }
    } 

For the sake of the example, the creation settings are set using static constructor, which still requires the class to change, in real scenario I'd add a AddSettings method for this or rely on IoC container (if it'd provide such functionality).

By doing this you have the advantage of loose coupling (you can change how the objects are actually constructed in separation) and can add new types of shapes anytime you want without even rebuilding the factory. Plus you are able to provide shape-specific creation params to constructors.

Of course considering just this simple example of building shapes this seems over-engineered a little bit, but that's the approach I follow for more complex, real-life scenarios.

Canvass answered 31/8, 2011 at 12:52 Comment(0)
F
2

The main point of the factory pattern is to de-couple the client from the creation of objects.

In your second example, the client has hard-coded the shape to create, such as MakeCircle, and therefore tightly couples the object creation and the client.

Faitour answered 31/8, 2011 at 11:34 Comment(5)
may i ask what way do you use ?Hazardous
If I was using a Factory Pattern I'd use something like the first example. However, I find dependency injection more useful in most cases.Faitour
OK, that sound fair. so what your saying is rather then using a factory pattern you prefer to use DI in most cases ?Hazardous
It depends on the situation, but yes.Faitour
You could use an Interface of type IFactoriedObject and have your factoried classes inherit that. You know what type of factory you're creating so you should be able to do it directly without having to go through logical if/then/select/case/norris statements.Italian
M
2

If you think the use of strings in the first method to select the desired shape is ugly, why not use enums?

Momism answered 31/8, 2011 at 11:51 Comment(2)
+1 for strong typing. The trouble of course is that you're back to maintaining a list of acceptable types. This isn't a breaking change and IMO it's worth the "effort".Buhler
using Enum make you maintaining more then just the factory it self, i believe.Hazardous
M
1

What the two you list here are called Simple Factory, The first one is better, because creation is mainly decided by parameter not method.

Actually Factory Method Pattern is official, Let's say there is a IFoo, and there are two implementation FooA, FooB as follows:

public interface IFoo
{
}
public class FooA : IFoo
{
}
public class FooB : IFoo
{
}

Then there is a problem when use IFoo in client application - How to create an implementation instance? Coupling exist because client depend on the creation of FooA / FooB, even FooC in feature, so we need de-coupling. We move the creation responsibility of IFoo implementation instance to another interface :

public interface IFooFactory
{
    IFoo CreateFoo();
}

to create FooA, we need:

public class FooAFactory : IFooFactory
{
    public IFoo CreateFoo()
    {
         return new FooA();
    }
}

to create FooB, we need:

public class FooBFactory : IFooFactory
{
    public IFoo CreateFoo()
    {
         return new FooB();
    }
}

The effect here is, when there is a FooC, we do not need to modify existing Factory, we just need to need implement another FooCFactory.

Mimeograph answered 31/8, 2011 at 12:37 Comment(0)
I
0

Personally I like the first. It allows you to easily expand the creation list. On the other hand the second relies on distinct methods to create new objects. If you add a method for a new shape it will break the ABI. You should change those methods to protected so new additions will keep the public interface and derived classes can still change how objects are constructed.

Individuality answered 31/8, 2011 at 11:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.