4

I get the idea of the factory pattern, but I feel that it is really not necessary to use this pattern.

For example, below is some code I saw (C#) that use factory method:

public interface IAnimal
{
   void Speak();
}

public class Dog : IAnimal
{
   public void Speak()
   {
      Console.WriteLine("Dog says: Bow-Wow.");
   }
}

public class Tiger : IAnimal
{
   public void Speak()
   {
      Console.WriteLine("Tiger says: Halum.");
   }
}

public abstract class IAnimalFactory
{
   public abstract IAnimal CreateAnimal();
}

public class TigerFactory : IAnimalFactory
{
   public override IAnimal CreateAnimal()
   {
      return new Tiger();
   }
}

public class DogFactory : IAnimalFactory
{
   public override IAnimal CreateAnimal()
   {
      return new Dog();
   }
}

and client can invoke:

IAnimalFactory tigerFactory = new TigerFactory();
IAnimal aTiger = tigerFactory.MakeAnimal();
aTiger.Speak();  //3 lines of code, plus needing of extra factory classes

but Client can also do like:

IAnimal aTiger = new Tiger();
aTiger.Speak();  //only 2 lines of code

we can see that only 2 lines of code is needed, and we don't need to define factory classes. so why takes extra steps to define and use factories?

Ant P replied that RandomNumberOfAnimalsGenerator needs a factory, but below is my version of the class, still doesn't need any factory.

public class RandomNumberOfAnimalsGenerator
{
    private readonly animal ;

    public RandomNumberOfAnimalsGenerator(IAnimal animal)
    {
        this.animal = animal;
    }

    public List<IAnimal> GetAnimals()
    {
        var animals = new List<IAnimal>();
        var n = RandomNumber();

        for(int i=0; i<n; i++)
        {
            animals.Add(animal);
        }

        return animals;
    }
}

and client invokes:

var RandomNumberOfAnimalsGenerator = new RandomNumberOfAnimalsGenerator(new Tiger());

still doesn't need a factory

6
  • 3
    A factory object can be passed as a parameter, making code that uses it create different classes for different callers.
    – Erik Eidt
    Commented Jan 14, 2020 at 10:36
  • @AntP yes of course I know that. Your example is a little bit weird to me since you add SAME type of animal(I know they are DIFFERENT instances). From David Arno's answer, now I see why we need factory, thank you anyway Commented Jan 14, 2020 at 11:04
  • 2
    As noted in pschill's answer, you are describing the abstract factory pattern not the factory method pattern
    – JimmyJames
    Commented Jan 14, 2020 at 16:15
  • 3
    Your RandomNumberOfAnimalsGenerator doesn't make a random number of animals. It makes exactly 0 new animals, but it adds the same animal to the list several times. Animal factory version: pass it "dog", get [Fido, Spot, Max]. Your version: pass it "Fido", get [Fido, Fido, Fido].
    – user20574
    Commented Jan 14, 2020 at 16:29
  • IAnimalFactory tigerFactory = new TigerFactory(); And then someday TigerFactory gets switched out for DogFactory, but the variable names will be left as is because scope propagation and too much effort and than new people will be brought into the project and the chaos will be glorious. :3
    – Tezra
    Commented Jan 14, 2020 at 17:43

8 Answers 8

8

I'm not sure yet another answer is needed here, but you asked for your code to be modified to explain the purpose of factories. So perhaps the following will help.

Firstly, I'm going to change your IAnimalFactory to be an interface, rather than an abstract class. It serves no useful purpose being the latter. Also, we likely will have some criteria around what sort of animal we want for a specific circumstance. So let's have an enum that defines that criteria:

public enum AnimalType
{
    Pet,
    Wild
}

Then we can create our factory interface:

public interface IAnimalFactory
{
    IAnimal CreateAnimal(AnimalType typeofAnimal);
}

So now we have a means of letting other parts of the code create an animal, without having to know anything about what animals exist. We simply get to specify whether we want a wild one or not:

public void CreateAWildAnimalAndMakeItTalk(IAnimalFactory factory)
{
    var animal = factory.CreateAnimal(AnimalType.Wild);
    animal.Speak();
}

The only thing left to do is create an actual factory. Let's keep that simple:

internal class SimpleAnimalFactory : IAnimalFactory 
{
    public IAnimal CreateAnimal(AnimalType typeofAnimal)
    {
       return typeofAnimal == AnimalType.Wild ? new Tiger() : new Dog();
    }
}

And then it gets used elsewhere in the code:

CreateAWildAnimalAndMakeItTalk(new SimpleAnimalFactory());

But dogs can be wild too, so we might want to offer a different implementation of the factory:

internal class RandomWildAnimalFactory : IAnimalFactory 
{
    private Random _random = new Random();

    public IAnimal CreateAnimal(AnimalType typeofAnimal)
    {
        if (typeofAnimal == AnimalType.Pet) return new Dog();

        return _random.Next(2) == 0 ? new Tiger() : new Dog();
    }
}

Then we can call our method with the new factory, without having to change any other code:

CreateAWildAnimalAndMakeItTalk(new RandomWildAnimalFactory());
4
  • thank you very much. This example solve my problem! Commented Jan 14, 2020 at 10:57
  • 2
    to put it in one sentence, a factory move if else statement from client side to concrete factory. Commented Jan 14, 2020 at 11:03
  • 11
    @secondimage That's not at all what it does. It moves the responsibility of what is created away from the thing that needs it to be created. What that means in practice is totally dependent on the scenario. I need a factory when I want to control how and when an object is created but I want something else to dictate what is created.
    – Ant P
    Commented Jan 14, 2020 at 15:55
  • 2
    Imagine a game, where you have enemies appearing in a particular pattern. You want to be able to create a bunch of any enemies, all of the same type, in any pattern. So you have a EnemiesAtRegularIntervals, EnemiesAtRandomIntervals, EnemiesOnceAfterDelay classes and each of them takes an EnemyFactory (or a Func<IEnemy>). Now the consumer gets to decide what enemies are created, but the pattern decides when. There's no implication of an "if else" statement here - the factory could just be as simple as return new TankEnemy();.
    – Ant P
    Commented Jan 14, 2020 at 15:57
7

Factory methods have a number of advantages. Mainly, they avoid the inbuilt limitations of constructors (can only have one name, cannot use caching, etc.).

Entire Factories are used mainly to decouple the client code from the concrete types used to instantiate the interface. But your example doesn't do this. Your client doesn't have to know the Tiger type, but instead it has to know the TigerFactory type, which is no improvement.

In my view, this is cargo cult programming - someone was told to use a factory and obeyed without understanding what the point of factories is. The proper thing to do would have been to have an AnimalFactory that can instantiate both tigers and dogs - but only if it can determine which to provide when. Otherwise, the decision about the concrete type of animal to use must stay with the client.

4
  • sorry I still don't get it. Could you modify my code to make it necessary to use Factory? Commented Jan 14, 2020 at 8:13
  • 2
    @secondimage There isn't a short piece of code that needs to use factory. It does become useful when the decision of what to make occurs thousands of lines (and billions of nanoseconds) before anything actually gets made.
    – Caleth
    Commented Jan 14, 2020 at 9:36
  • @Caleth can you use the concept of IAnimal to show me the easiest example that I need to use a factory, I will to find a counter example just like I did on RandomNumberOfAnimalsGenerator Commented Jan 14, 2020 at 9:50
  • @secondimage It isn't a case of "need/not need", its a "this is preferable to the alternative". That really only comes around in large systems. The simplest thing I can think of to describe an example is rendering options in PC games. Based on the chosen settings, you could have e.g. different IModelFactory, ITextureFactory, IAntiAliasingFactory handed off to the rendering component. But that doesn't need to be Factories
    – Caleth
    Commented Jan 14, 2020 at 9:58
5

There are different types of factories that serve different use cases. Often, you want to create objects of different (sub-) classes depending on runtime arguments. For this case, a simple function or a non-polymorphic class can be sufficient:

public class AnimalFactory
{
    public static IAnimal Create(String typeName)
    {
        if (typeName == "Tiger")
        {
            return new Tiger();
        }
        if (typeName == "Dog")
        {
            return new Dog();
        }
        // handle error, for example:
        throw Exception("Unkown type name: " + typeName);
    }
}

This factory allows you, for example, to create different animals depending on user input:

String userInput = Console.ReadLine();
IAnimal animal = AnimalFactory.Create(userInput);
animal.Speak();

As you already noticed, there is no need for a base class / interface IAnimalFactory with different factory subclasses. Here, those would only complicate the factory usage.

With above factory, whenever calling Create, you must provide the argument userInput that allows the type selection. However, in some cases, you want to separate the type selection from the actual creation. Take a look at the following example:

public class AnimalStore
{
    IAnimalFactory m_animalFactory;
    double m_price;
    public AnimalStore(IAnimalFactory animalFactory, double price)
    {
        this.m_animalFactory = animalFactory;
        this.m_price = price;
    }
    public void SellAnimalToUser(User user)
    {
        if (user.money < this.m_price)
        {
            throw Exception("Not enough money");
        }
        user.money -= this.m_price;
        user.AddAnimal(m_animalFactory.CreateAnimal());
    }
}

The AnimalStore is not polymorphic. However, different stores can still create different animals. When calling SellAnimalToUser (which calls Create), you dont need any argument that selects the correct animal type.

AnimalStore tigerStore = new AnimalStore(new TigerFactory(), 1000.);
AnimalStore dogStore = new AnimalStore(new DogFactory(), 200.);
User peter = new User();
peter.money = 5000;
tigerStore.SellAnimalToUser(peter);
dogStore.SellAnimalToUser(peter);

The problem of separating type selection from object creation can also be solved by other means. For example, you could have a non-polymorphic AnimalFactory that lets you specify the String typeName in its constructor instead of its Create function. Or you could inject functors instead of factories. These methods have their own advantages and disadvantages and which you want to use usually depends on how you want to use it.

12
  • 1
    I don't understand why this was downvoted. The question is clearly about the abstract factory pattern, not factory methods as it claims. The abstract factory pattern is largely overused when DI would be a better fit. Factory methods have few downsides.
    – JimmyJames
    Commented Jan 14, 2020 at 16:11
  • @JimmyJames, it’s because life’s too short to worry about real or imagined differences between near-identical patterns. They are all factories. So an answer that starts with a pedantic criticism of the specific type of factory being discussed needs a downvote. It’s not important.
    – David Arno
    Commented Jan 14, 2020 at 17:03
  • @DavidArno They are not near identical. That's blatantly false. Specifically the part the OP is complaining about is not part of the factory method pattern.
    – JimmyJames
    Commented Jan 14, 2020 at 17:06
  • 1
    @DavidArno "DI and factories are orthogonal unless one uses a static factory" You still haven't understood the difference between the two patterns, apparently. Saying they are the same thing is like saying rooms and buildings are the same thing. The abstract factory pattern is built on top of the factory method pattern. This is explained right in the first paragraph of the wikipedia article.
    – JimmyJames
    Commented Jan 15, 2020 at 15:12
  • 1
    @DavidArno "a static factory, which would be an anti-pattern" That's an interesting viewpoint which goes against that of one of the most influential software designers in recent history. On balance, I would say I find him more credible.
    – JimmyJames
    Commented Jan 15, 2020 at 15:26
4

The benefit of the Factory Method pattern is in expressing the fact that a piece of code does not want/need to know how to obtain an IAnimal.

In fact, interfaces are often viewed from the wrong perspective: you can never force client code to use your interface.

Rather, the client code can specify that it requires an interface, in this case, "a way to create animals".

It would not be so dumb that the client code even defined the interface itself, expressing that: "you take care of creation, I'll put them in a zoo".

Note that this pattern was defined in an era where programming languages had no lambda expressions. In today's context, many of the patterns have become obsolete. The Factory Method can now be implemented with a simple Func<IAnimal>:

public void myCode(Func<IAnimal> createAnimal) {
   var a = createAnimal();
   ... // stuff with a
}
1
  • 1
    "Note that this pattern was defined in an era where programming languages had no lambda expressions". I'm not sure this is true as the GoF patterns were invented for C++ (I think) and C supported function points for many years prior to its publication. But I completely agree with you that abstract factory implementations using interfaces and classes are over-engineered compared with a simple Func<T> solution.
    – David Arno
    Commented Jan 14, 2020 at 12:34
0

You asked for an example of why you'd ever need a factory but you haven't really been given one yet.

Suppose you have a piece of code that creates a random number of animals. How do you decouple this from the details of how to create a specific type of animal?

The answer: a factory.

public class RandomNumberOfAnimalsGenerator
{
    private readonly Func<IAnimal> createAnimal;

    public RandomNumberOfAnimalsGenerator(Func<IAnimal> createAnimal)
    {
        this.createAnimal = createAnimal;
    }

    public List<IAnimal> GetAnimals()
    {
        var animals = new List<IAnimal>();
        var n = RandomNumber();

        for(int i=0; i<n; i++)
        {
            animals.Add(createAnimal());
        }

        return animals;
    }
}

Without this factory, RandomNumberOfAnimalsGenerator needs to know how to create every type of animal.

9
  • This is still fairly contrived, and could instead be public class RandomNumberOfAnimalsGenerator<T> where T : IAnimal { ... }
    – Caleth
    Commented Jan 14, 2020 at 9:39
  • @Ant P I have updated my post to create a RandomNumberOfAnimalsGenerator without using a factory, could you have a look? Commented Jan 14, 2020 at 9:44
  • @secondimage That creates a list of a random number of references to the same animal
    – Caleth
    Commented Jan 14, 2020 at 9:50
  • @Caleth yes it will create only the same type of animal, but how you can create different type of animals? can you show me the client code that how to invoke RandomNumberOfAnimalsGenerator? I don't think a func delegate can allow to do that Commented Jan 14, 2020 at 9:52
  • @secondimage var randomNumberOfRandomAnimalsGenerator = new RandomNumberOfAnimalsGenerator(() => RandomBoolean() ? new Tiger() : new Dog())
    – Caleth
    Commented Jan 14, 2020 at 10:00
0

One use I haven't seen in these answers that's really common but you are kind of looking at the problem backwards (Your example code is both consuming and creating the factory, which isn't generally useful). A good use for it is where there are 2+ sets of code interacting (maintained by completely different teams).

Let's take something like a log library as an example... This might be a utility class that you use to log out to a file.

Suppose the log has quite a few destinations, File, database, console, … that you can configure through either configuration commands or a config file, but what if you want to log to some other device--a remote port, or some strange old paper tape punch you found in your closet? On top of that you want any other libraries that you are using that might use the same logging software to use YOUR special logging back-end.

In other words, how can you supply the logger with code it should run when it logs?

I can see 3 ways:

  1. add your class name to the logging library's config file
  2. Provide the logger with a concrete instance of your logging back-end
  3. provide a factory to the logging library that it can use to create it's own instances of your logging back-end.

2 and 3 are close--the main difference is that if the library needs a new logging backend each time the client code creates a logger, then solution 2 wouldn't work and you'd need a factory.

Looking at it from the user's point of view you hardly even see that it uses an abstract factory, but when you look at it as an implementer of the logging library, it seems quite necessary.

-2

Your code is not an example of factory method. Factory method is just one single method, it is usually a static (in case of java). Having abstract method which is overloaded in different derivations doesn't make sense because in that case you need to create real single factory method to instantiate entities of implementation.

I suppose your code is part of Factory pattern (not FactoryMethod) which is different. Factory includes factory method as a starting point to create itself. Moreover IFactory can (and should to be useful) contain multiple methods for each interface in a set of types involved in process of multiple implementation. For example.

public abstract class IAnimalFactory {
    public abstract IAnimal CreateAnimal();
    public abstract ILocation CreateLocation();
    public abstract IFood CreateFood();
}

class Zoo extends ILocation;
class Savannah extends ILocation;

IAnimal.placeTo(ILocation);

And so on.

-2

Your RandomNumberOfAnimalsGenerator doesn't make a random number of animals. It makes precisely zero animals, in fact. What it does do is create a new list, containing several references to the same animal.

For a RandomNumberOfAnimalsGenerator, I should be able to pass it "dog" and get back a list: Fido, Spot, Max.

If I then feed the dogs: foreach(IAnimal a in randomlyGeneratedAnimals) {a.Feed();} then I feed three dogs once.

With your RandomNumberOfAnimalsGenerator, I can pass it "Fido" and get back a list: Fido, Fido, Fido.

If I then feed the dogs: foreach(IAnimal a in randomlyGeneratedAnimals) {a.Feed();} then I feed Fido three times.

In your program, I can't tell the difference, because all dogs are identical, because they don't have any fields. If I add a field:

public interface IAnimal
{
   void Speak();
   void Feed();
}

public class Dog : IAnimal
{
   public void Speak()
   {
      Console.WriteLine("Dog says: Bow-Wow.");
   }
   private int Hunger = 5;
   public void Feed()
   {
      Hunger--;
      Console.WriteLine("Hunger level is "+Hunger);
   }
}

then you will get different results, if you have the same dog three times instead of having three different dogs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.