Factory Method Design Pattern

Actually, this is quite simple pattern. However, there are so many inappropriate examples (toy code, non-understandable and useless ones) and even more cryptic explanations that you can easily get confused and think what is the point in using this design pattern? It contains lots of awful examples where using Factory Method does not show its’ possible and practical purpose in no way. For example, let us take a look into a Book Factory! https://sourcemaking.com/design_patterns/factory_method/php/1

Seriously, am I supposed to use this for some Books? Why? What is so special about the book that the book having different title, publisher or any other attribute that can be represented in a primitive data types, i.e. so special that I am supposed to create a Book Factory? Builder for books? Maybe, since there might be massive amount of attributes I would like to set comfortably and abstract setting them. Using Prototype for the Book itself? For the Book itself no way, but if the source is some remote data source, then Prototype can be useful, so Book can really implement ICloneable. But Factory Method for the Book? Maybe there are some ways, but I tend to simplify most difficult processes in most simplistic way possible, so it would be easier to manage them later. Thus, I think Book should not be used as an example for Factory Method. It is just too misleading from actual purpose of this awesome design pattern.

In order to find a proper example for usage of Factory Method, first we should take a couple of points why it is used. Some of the points mentioned in various resources are the following:

  1. Abstraction of new object creation. Yes, this is correct, and it is extremely useful in the IoC Containers where Factory Method is used in this way. However, IoC Containers for this article is a bit too complex example to get real understanding of Factory Method, thus I will leave it out here.
  2. Some say that way how objects are instantiated (created newly in memory or returned from some cache) should not matter for the client. Well, I am not so sure. Even if client will know that new object gets put somewhere and somehow in the memory, I think no client will know exactly the internals of that. If the “new” operator would be really harmful as some people tend to say, then no Object Oriented Programming Language would have operator “new”. As a client, I might want to write code in a way that does not restrict me in any ways. Or at least I would like to have intuitive enough API to write the code. In any case, it is wrong to assume what other developers want from me as an API developer. I can only assume the most standard needs: intuitive and easy to use API, understandable documentation, practical and useful examples (not some too primitive examples like “Hello, World”). However, I really agree that “new” should be avoided if it is possible to get the result without in a more elegant way. But still it should be used somewhere. We just should find proper place for it, not avoid it.
  3. Abstract logic that would come out of direct composition of two actual objects. And this can be quite a real reason to use Factory Method. For instance, you might have some main class for doing something, then you might have another class which also does something where another class has something that does something, and so on. Providing an interface as a proper closure for such type of logic really helps, since it becomes unit testable.
  4. Another thing that is suggested is to use some static class for the main factory. Actually, it is one of the antipatterns that you can think of. If possible, you should avoid this at any costs. What if I intend to use the factory in some model class that creates different objects based on the input provided? With static classes, I would be unable to write unit tests in isolated manner.
  5. And so many more explanations.

There are so many explanations due to the following reasons:

  1. Some people confuse Factory Method with Factory. They are different. Factory is used to create objects whose classes resolve to the same top level definition (parent/grandparent) based on some input parameters. Some even say it is not a pattern, and just a programming technique. Well, we have in this world lots of grammar purifiers. Probably, there is no exception in the developers’ world. So, what actually Factory is? Yes, it is a software development technique. And what a Design Pattern is? Also, it is some sort of software development technique. Thus, simple Factory is also a proper design pattern, since it is a common way to solve the problem specified. Factory is just not the part of GoG patterns. Maybe because it is so obvious and simple that any developer would think about it out of intuition. Still, I think Design Patterns are much more than GoG classics in today’s world.
  2. Some even confuse Factory Method with Abstract Factory. It is a rare case, but I have seen this in code working on the project a couple of years ago.
  3. And most probably just have not enough knowledge in Mathematics, verbal communication is not good enough regarding extremely important things. In other words, they do not actually understand what the Factory Method is, and just pretend to understand. However, they use it all the time. Which is strange, but it happens so.

Thus, I am going to explain this pattern once and for all not to make any confusions regarding it. It is pretty sad to see so many toy examples that are never going to help. So, what example for the Factory Method can be useful? Document factory method INTEGRATED into some document storage medium might be useful example where there is IDocument interface that gives as FileName (e.g. example.json) and its’ JSON representation. For instance, we might have some byte stream and we want to be able to store it in different document storage formats: DOC, DOCX, PDF, HTML, and so on. Currently, we have no idea how to convert that byte[] stream to PDF, DOC, DOCX, and so on. Maybe we do not even know what to expect in that byte[] stream. So, let us create a base class for storage medium based on these unknowns:

// Product participant.
public interface IDocument
{
    string AsJSON { get; }
 
    string FileName { get; }
}
 
// This has not to be a factory or something. It is just a Creator participant, and that is it.
public abstract class DocumentStorageBase
{
    // This is the factory method we are going to use.
    // This is the main point of Factory Method. You can not know exactly what type of document will get created here, but
    // you know that there will be some fixed interface (a.k.a. Product participant).
    protected abstract IDocument Create(byte[] content);
 
    // Just a simple storage method. We have the interface, the data in it, thus we know how to save it in some file.
    public void Store(byte[] content)
    {
        var document = Create(content);
 
        var fileName = document.FileName;
        var json = document.AsJSON;
 
        // Store the document somewhere.
        // Not implementing here, since I want to show the use for pattern, not implementation. You can think of any implementation you like.
    }
}

Then, let us say we know we will have to be able to store PDF documents. So, we introduce two new classes.

// Concrete Product participant.
public class PDFDocument : IDocument
{
    public string AsJSON { get; set; }
 
    public string FileName { get; set; }
}
 
// Concrete Creator Participant.
public class PDFDocumentStorage : DocumentStorageBase
{
    protected override IDocument Create(byte[] content)
    {
        // Some difficult conversion logic that is able to get PDFDocument object from byte[].
        // This class would definitely include some dependency injection.
        return new PDFDocument();
    }
}

And that is it. This is everything about Factory Method. We covered all of the participants, and I have shown a pretty useful example which can really get benefits from the Factory Method. As you can see, Factory Method is extremely powerful pattern, and can be used in such cases where you know just a resulting interface/base class (a.k.a. Product participant), and you want someone else to create Concrete Product participants (i.e. they are created by Concrete Creator participants). And Creator itself is just an abstract class exposing an API method to override Factory Method which is used to create Concrete Product participants.

To sum up everything, Factory Method can be defined in the following way:

  1. It is a Creational Pattern allowing us to defer responsibility of object creation to the child-level through parent-level abstract method definition.
  2. There are four participants: Product (base interface both Client and API developer agree on), Creator (base class which introduced Product creation Factory Method which is abstract and should be implemented by child classes), Concrete Creator (implements the Factory method), Concrete Product (instance of Product interface created by Concrete Creator).
  3. It is useful when you know nothing about concrete products that might be instantiated, but you have a pretty good idea of the interfaces, and you exactly know what needs to be done. In other words, you know WHAT, but you do not know HOW, yet. Or you just want to leave HOW part for later.

Finally, there are some pretty nice explanations regarding Factory Method, too. At least the following one is the single one I was able to find where at least explanation is nice: https://exceptionnotfound.net/the-daily-design-pattern-factory-method/ . Explanation is short, clear, and from this you can really get the idea HOW to use Factory Method. But not sure about WHY. Example is original maybe, but not very useful from the real-world perspective, since it does not show WHY Factory Method should be used. I can code all of the sandwiches without any of the Design Patterns, and I would not lose anything. However, I would lose massive amount of nerves, time, and lots of other stuff if I would try to code smart Website Crawler by trying to include all of the rules in a single class. Or to create God of Documents (a.k.a. God Object that is able to create and store PDF, DOC, DOCX, HTML, XML, and so many more document formats in a single class). By using Factory Method, I can concentrate on the things I know right now, and do not bother that I might not know right now something, since I will always be able to extend the class without violation of SOLID (especially Single Responsibility and Open/Closed principles), and do not worry too much of some unknowns. That is why Factory Method can be used. But for sandwiches, books, colors, shapes… These examples are inappropriate. No one codes different classes for books if title is different. And if one does, then software design in that project should be very messy.

Leave a Reply

Your email address will not be published. Required fields are marked *