markdown guide
 

It's 12am. The pipes in your house break. There is water everywhere. You are worried about property damage.

You call Pick-Your-Own-Plumber.
The operator asks you what your pipes are made of.
You don't know.
The operator asks you how many pipes you have.
You don't know.
The operator says: I can't give you a plumber to fix your pipes, if you can't tell me how to fix them.
Needless to say, you hang up, angry.

You call Plumbers-For-All-Occasions.
The operator asks you what's wrong.
You say: I don't know and I don't care, my pipes are broken. All I need is someone who can fix my pipes -- I don't care how, I don't care whether they do it with geometry or magic, I JUST NEED SOMEONE TO FIX MY PIPES.
The operator says OK, we will send someone to fix your pipes.

The plumber comes.
He looks at your pipes, and based on what he sees, he does the right thing.
He wasn't sure exactly WHAT he would do to fix them until he got there, but he knew he COULD fix them, because pipe fixing is something he knows how to do.
He decided HOW to fix them once he got there and not before.

Plumbers-For-All-Occasions is a factory.

 
 

If you just need to create an instance of a single class, then something like new Class() is totally fine. Let's say though you find yourself writing the same conditional code, like below, in multiple places:

let c = null;
if (condition1) {
  c = new Class1();
} else if (condition2) {
  c = new Class2();
} else {
  c = new Class3();
}

c.use();

You don't want to duplicate this logic, so a factory will allow you to put this conditional logic to instantiate the object you want in one place. For example:

const c = createClassInstance(config);
c.use();

// createClassInstance is a factory function. 
// 'config' is some kind of object that 
// contains enough information for the factory 
// to decide what kind of object you want the 
// factory to make for you.
function createClassInstance(config) {
  if (condition1(config)) {
    return new Class1();
  }

  if (condition2(config)) {
    return new Class2();
  }

  return new Class3();
}

We assume that Class1, Class2, and Class3 all have the function use.

With languages that support "duck typing", as long as the classes all support the use method, that's good enough for this to work. In some cases these classes may all be subclasses of a common base class or implement a common interface. With statically typed languages, I think that has to be the case - it is in fact the case with a language like Java for example.

There are some other cases where you may want to use something like a factory. For example, the Singleton pattern is used to make sure you always get the same instance of an object each time you ask for one anywhere in the code. You can use a factory function to do this. The function will make sure that you're always getting the same instance. Oftentimes this is written to operate lazily, so you'd check to see if you had an instance already, and if so, you'd return that instance. Otherwise you'd create one first, then return it. If you have some sort of connection pool, the same kind of idea can be applied. So I think there are many situations in which you might want to use something along the lines of a factory.

 

You are in an icecream parlour where you can choose between 100 flavours and 50 toppings, but usually the clients want a sundae chocolate & vanilla!
So you can do a fast line where you say "the classic" then you obtain your sundae with chocolate and vanilla insted of making the slow line and specify everything detailed.

With code:
IceCreamParlour.theClasic()

vs
i = new IceCream();
i.presentation(SUNDAE)
i.addFlavour(chocolate)
...

 

When a person makes something, for example a fork, it takes them a certain amount of time. If the person has to make a lot of forks then, if they try to do so quickly, each fork can come out with differences between them and even things wrong. Perhaps some of the forks are shorter than others, or maybe some break more easily. If the person takes their time to make each fork they will be able to make them all to a similar standard, but they won't be able to make very many.

If you look at the fork in our cutlery draw you can see that they all look the same and none of them break. If you go to a shop to buy forks, you'll see there are lots of forks. Always more forks than there are people who need them. If it takes a lot of time for a person to make a fork well, how did we get so many forks?

What happened was that someone came up with a machine that can take metal and turn it into a fork. This machine can work faster than a person because it only has to do one thing: make forks. The machine will melt the metal, pour it into a mould that is the shape of a fork and once the metal has cooled there will be a new fork.

In fact, the machine will be made to make many forks at once. It will be made to take many different shapes of fork mould. Not all forks look the same, after all.

The building this fork making machine is in is called a factory. Shops send orders to the factory telling it how many and what shape forks they want. Then we go out and buy forks.

In programming almost none of this is relevant. The thing we call a "factory" is nothing like a factory. It can only produce one thing at a time and we get the thing directly from the factory, not from a shop. It's more like one of the machines that would live in the factory, but limited to producing one of the things at once.

The programmers factory (let's call it a phactory) is a way of producing a thing that is basically one type of thing, for example a user, but has some specific behavioural difference, for example, a user that logs in via OIDC, or a user that logs in via the regular username/password combo.

So our phactory would look something like

   class UserPhactory():
       def get_user(login_type):
           if login_type == 'OIDC':
               return OIDCUser()

           if login_type == 'normal':
               return User()
 

After reading through the rest of the comments, this is what I came up with. Please correct me if I am wrong!

You want to eat an ice cream with 2 scoops of flavors, mint and strawberry. On top of that, you want to drizzle it with chocolate sauce and be placed in a waffle cone. For this to happen, you have to do it all by yourself, adding the stuff you want one by one.

For Factory Pattern, you go to the ice cream shop and say, I want an ice cream with 2 flavors, mint and strawberry, drizzled with choclate sauce and place it in a waffle cone. Without you doing anything, BOOM! You got what you want.

Edit: From now on, whenever you want a particular ice cream, all you have to do is to tell the ice cream shop what you want, instead of creating it yourself

 

You work as a salesperson where you travel around a lot. You use this nifty app on your laptop which can connect to the internet and get the latest info for your customer. This lets you be really up to date when you go to their office.

(Pretend this is how things are still done. The explanation works better this way :)

But maybe your internet connection is spotty in places and your program can't always get the very latest information because sometimes there's no internet. To make up for this, whenever it CAN connect it saves a copy of the latest info for your customers to your laptop. Later, if there's no internet connection the program can at least use this file so you're not completely blind.

So, your program has two different libraries for getting customer data: one it uses when there's an internet connection, and one is uses when there isn't and it has to use that file it saved from last time. But the libraries are written so that they've got all the same functions/methods. GetCustomerOrders, GetCustomerHistory, etc. are in both libraries, it's just that one goes to the internet and the other goes to the file on disk.

The "factory" part of this is that whenever your program starts up, it asks a special object to get it the library which gets access to the customer info. This "factory" object might have a single method: GetCustomerLibrary() or something. Depending on the internet connection, it hands back the connected version or the non-connected version of the customer information library.
But your program doesn't know the difference. It doesn't care. The two version of the library both do all the stuff you need.

As a side benefit, this pattern can be really useful in the early stages of app development. Maybe your app is going to access a database, but the database hasn't been completely built yet. Does this mean you have to wait until it is built?
No! Just have a version of your library which accesses a small file of dummy data, or an Excel spreadsheet, or something. As long as it has the same methods as the version which will use the database, you can develop with the file/Excel-based version until the database is online.

 

Suppose that you want a duck. You don't care much about it, you just want it to quack and nothing else.

To get it you don't build it yourself, you go to the duck factory then ask for a duck and boom you get a duck.

This becomes increasingly useful if there is a city-wide policy on ducks. Suppose that some people need ducks to be of a specific color. When they move in town, the mayor can order ducks to be of the right color. You still don't care because you need them to quack but the new people are happy because they have the right color.

This last paragraph however is a more advanced topic called inversion of control but that fits in the same logic than factories in my opinion (and it's where the principle really shines).

Also suppose you're on the Java island and that everything is boring and painful and limited. Then the factory can relieve some of the pain that you don't find in other places.

 

You want to rent a vehicle. Your options are "small", "mid-size", "suv".

You ask to rent a "suv".

All you know is - you got an suv. But in reality, it could be a ford, gm, etc.

But you don't care. You just want some generic "suv".

The rental dealer is like a factory. You ask for something generic. They give you something real.

Classic DEV Post from Dec 2 '18

How did I started learning a new technology

Personnal view of how and why I learned a new technology

Germán González profile image