Domain model classes
Object-orientation is great when classes represent actual domain model objects. For example, if we're modeling animal sounds, Dog
and Cat
classes make good sense:
interface IAnimal
{
string Speak();
}
class Dog : IAnimal
{
public string Speak() => "Woof";
}
class Cat : IAnimal
{
public string Speak() => "Meow";
}
Factory pattern
Now, let's say we need to write a function that creates an arbitrary animal and asks it to speak. Unfortunately, there's no way to add a constructor to the IAnimal
interface. One way to work around this limitation is the Factory design pattern, which creates a separate "factory" class for each of our domain model classes:
interface IAnimalFactory
{
IAnimal CreateAnimal();
}
class DogFactory : IAnimalFactory
{
public IAnimal CreateAnimal() => new Dog();
}
class CatFactory : IAnimalFactory
{
public IAnimal CreateAnimal() => new Cat();
}
With the new IAnimalFactory
interface, we can create dogs and cats and make them speak:
class Program
{
static void Main(string[] args)
{
Run(1, new DogFactory());
Run(2, new CatFactory());
}
static void Run(int n, IAnimalFactory factory)
{
var animal = factory.CreateAnimal();
Console.WriteLine($"Animal #{n} says '{animal.Speak()}'");
}
}
// output:
// Animal #1 says 'Woof'
// Animal #2 says 'Meow'
This works fine, but it adds a considerable amount of new code and conceptual overhead, because every domain model class now requires a separate factory class as well. The extra level of indirection can quickly become confusing. Is there a better way?
Factory functions
Functional programming lets us get rid of factory classes altogether. Instead of passing an IAnimalFactory
to Run
, we can instead pass a "factory function" of type Func<IAnimal>
. This takes over the role played by the factory object in the previous implementation:
static void Run(int n, Func<IAnimal> createAnimal)
{
var animal = createAnimal();
Console.WriteLine($"Animal #{n} says '{animal.Speak()}'");
}
We can use lambdas to create our factory functions with little ceremony:
static void Main(string[] args)
{
Run(1, () => new Dog());
Run(2, () => new Cat());
}
The output is exactly the same. By using functions as first-class objects, we've eliminated an entire category of classes and significantly simplified our code base! If you find yourself tempted to create a factory object in the future, consider using a factory function instead.
Top comments (19)
As presented, I can sort of see an advantage to the factory method technique from the standpoint of not knowing at compile time what concrete types will be available at runtime. (E.g. If the factory method is in a different assembly from the one containing the concrete types.)
My strongest argument against it though is that the factory method is tied to whatever class declares it. A class should only have one purpose, and if that purpose is to create objects matching a particular base class/interface, it should be a factory.
I don't generally do a separate factory for each class. Instead, it's one per Interface (or abstract class, or whatever the common base may be). That would look something like this:
This is a common pattern. But, as alluded to above, the drawback to this particular style is that you have to know all the concrete classes in advance.
A compromise then would be a factory class with a constructor which takes a name/value pair consisiting of an enum (e.g. AnimalType) and the matching creation function. The factory class then would have a
Create
method which takes anAnimalType
value as a parameter, looks up the matching creation method, and calls it. There could very likely be an argument on the factory'sCreate
to pass a data structure containing type-specific attributes such as weight, color, beak-size, number of feet, and so forth.Very rough version for illustration, almost certainly non-compiling:
Thank you for the detailed response. Examples are definitely helpful! :)
I think what you’ve done is fine since it’s basically a functional approach that avoids the explosion of traditional factory classes. My only suggestion is to use
Func<IAnimal>
instead of a delegate. The modern syntax is easier to read and work with, IMHO.The delegate is definitely a bit old school, but for purposes of illustration, I felt the explicit signature lent some clarity to what I was trying to communicate. In real-world code, a
Func<T>
might very well be preferable.As I commented elsewhere, factories which only wrap a
new
are good for demonstrating "Here's how a factory works," but don't provide much other value. Having a separate factory for each class, particularly when they're just "wrap thenew
", is something to avoid; I'm tempted to call it an anti-pattern.I suspect there's something similar at play here with the description of factory methods. I understand how to write them, you've communicated that pretty darn well. But I'm struggling with the compelling reason why they're preferable to well-designed factory classes.
Func are nameless. Making arguably "harder" to understand when you find it in the code. Creating a delegate allows you to name it and make easier to "inject" it using DI. And having a name also expresses what you intend to do with that function.
I don't know that this accomplishes the main issue, you still have to know the concrete class in advance. You don't have a concrete class but still have to recompile to add a new type to your enum. I feel that I shouldn't need to add all concrete types to my factory class. By using the author's delegate method, I can define all of my concrete classes where they best fit in my project and just implement a good interface that indicates all of the uses of that class.
The downside of this is definitely traceability though.. Getting a new person on the team to be able to find the source and see what's happening at a glance is a nice perk for sure, which doesn't happen in the more abstract version.
I started doing a lot of JS a year ago.. It seems it's tainted me.
The enum certainly forces a recompile, but you can use strings instead.
But the Creator methods (whether declared as delegates or Funcs) would encapsulate the knowledge of the concrete classes. All the factory needs to know is that it has a function to call and that function has a specific signature.
But, what if I'm building a Beagle and a German Shepherd?
I'd make sense to have two classes that build the same class Dog, but gives me a different ones, based on it's properties.
More code? You're right, but also much more readable.
I'm not sure I follow you. Are you saying that we could create
Beagle
andGermanShepherd
as subclasses ofDog
? That's true, but I don't see how that would change the situation much.Can you clarify, or give an example where a factory class makes more sense than a function?
I don't get why you need this factory anyway. Why not just calling the constructor directly ?
Good point. Because this is a toy example, each factory is only used to create a single animal, so they really serve no purpose. Typically, though, a single factory creates multiple objects - for example, in response to a recurring event, or corresponding to rows in a database, etc.
To keep things simple in our case, imagine if
Run
looked like this instead:Since we now create 10 instances of each animal class, some sort of factory makes sense, yes?
Sometimes, objects become too complex to be handled only by the constructor.
Sometimes you'll also want to apply domain rules in the creation of an object.
I feel some anti-pattern issues:
You can see where it is going.
This is no different from the factory pattern, which accepts any object that implements
IAnimalFactory
. I don't think there's any risk involved.I don't follow you. How does the factory pattern (or my functional version of it) lead to duplicate code? An example might help.
Isn't the whole point of factory is to make complex initializations easier? I am not able to see how this can be applicable when factory is not just a wrapper for new. Why would you even use factory (and look for a simplification) when constructor is already more than enough?
No, the point of the factory pattern is to create an object that implements a particular interface (
IAnimal
) without knowing the class of the object. You can take a look at an example here.Thank you for pointing this. I'm a Unity developer and in Unity we cannot use constructors at all (it breaks the engine). Plus, interfaces are sometimes anti-pattern (if not most of the time). This sometimes create confusion.
That’s interesting. Every C# example of a GoF factory design pattern that I’ve seen involves at least one factory class.
The examples for conveying a concept are rarely effective at showing the power of the concept. (E.g. A factory that simply wraps
new MyType();
).And the examples that show how powerful a concept can be (e.g. A factory that demonstrates the provider/strategy pattern) is rarely effective for demonstrating the concept of a factory at its purest level.
My own experience is that simple factories aren't good for much except demonstrating what a factory is. But factories tend to be where the "magic" part of a design pattern is implemented. (Strategy, Decorator, and even Visitor, are all built on Factory.)
I think we’re in agreement that factories are useful. My only point is that modern C# can accomplish the same thing using functional programming instead of OO classes.
(The GoF book was written before mainstream OO languages supported functional programming.)