Masonite Lessons - Using The Factory Pattern
Tags: python, framework, designpatterns
Published: 2019-01-17 04:13:22

---
title: Masonite Lessons - Using The Factory Pattern
published: true
description: Masonite architecture lesson. Using the Factory design pattern
tags: python, framework, design patterns
---

# Preface
	
[Masonite](https://github.com/masoniteframework/masonite) has a lot of very front facing and explicit design patterns. It has always been my goal that developers using [Masonite](https://github.com/masoniteframework/masonite) will become better developers by being exposed to these patterns either by use or by reading about them in the documentation and understanding through real world examples.

I will be creating these articles that talk about various design patterns and how I use them in my applications on a daily basis.

# Introduction

Design Patterns are pretty simple. We as developers encounter problems with our code. We as developers have 5 goals of software development is to deliver a product that is

* on time
* within budget
* fault free (no bugs)
* satisfies needs now
* satisfies need in the future

We as developers need to be able to accomplish these tasks in a way that can satisfy needs now and in the future. These are problems developers face all the time. Throughout the years, developers have encountered the same issues over and over again and the same way a carpenter has “tricks of the trade,“ so do developers. These tricks-of-the-trade are called Software Design Patterns. They are simply solutions to problems we encounter all the time in our development life.

Once you start to get good as a developer, you will be able to map issues to certain design patterns and be able to layout a software architecture to fit the needs of the problem you are solving.

# The Pattern

The factory pattern is used to instantiate an object at runtime. That’s it. It’s just a class that can return different types of objects dependent on whatever value is passed to it. For example you may pass in the value of `chocolate` into the `IceCreamFactory` and get back a `ChocolateIceCream` class.

This may need to be done at runtime which is where this pattern comes into play. The value of `chocolate` may be stored in a database column that is fetched for a certain user for example.

# Code Example

```python
class IceCreamFactory:

    flavors = {
        'chocolate': ChocolateIceCream,
        'vanilla': VanillaIceCream,
        'strawberry': StrawberryIceCream,
    }

    def make(self, flavor):
        return self.flavors[flavor]()
```

That's it. We just created a factory using the factory pattern. Now all we have to do is specify a flavor we need and we can get back the correct flavor:

```python
flavor = IceCreamFactory().make('strawberry') #== <some.module.StrawberryIceCream>
```

# The Problem - Real World Example

Here is a real world example of how I used this pattern. We are provisioning a server. For simplicity sake, we have 2 services we want to provision:

* Postgres
* Nginx

Now we need to provision both of these services on 2 different types of servers:

* Ubuntu
* Debian

Now notice here we have several different possibilities we can choose from:

* Installing Postgres on Ubuntu
* Starting Postgres on Ubuntu
* Stopping Postgres on Ubuntu
* Installing Nginx on Debian
...
... so on and so forth

There is an exponential number of possibilities, especially as we add new servers, new services or add layers in between them (for example installing via docker instead of bash commands).

How do we solve this issue? A bit of a combination of several patterns but we'll focus on the Factory for this article.

# Solution

The solution here is to use 2 factories.

The first factory will be a `ServerFactory` which will be responsible for fetching any one of several servers (Ubuntu, Debian, Centos, ..).

The second factory will be a `ServicesFactory` which will be responsible for fetching any one of several services (Postgres, Nginx, RabbitMQ, ..).

## The Server Factory

Using the boiler plate above let's go ahead and create our `ServerFactory`:

```python
class ServerFactory:

    servers = {
        'ubuntu': UbuntuServer,
        'debian': DebianServer,
        'centos': CentosServer,
    }

    def make(self, server):
        return self.servers[server]()
```

Notice we just changed out the ice cream flavors for servers (UNIX flavors?). 

## The Service Factory

Now let's do the exact same thing for services:

```python
class ServiceFactory:

    services = {
        'postgres': PostgresService,
        'nginx': NginxService,
        'rabbitmq': RabbitMQService,
    }

    def make(self, service):
        return self.services[service]()
```

notice all this code is the same boiler plate.

## Combining The Factory

Now if we think of it from a database perspective:

> A server **has many** services

Right? Since a server **has many** services, let's mimick that. Let's make the `UbuntuServer` have access to the `ServiceFactory`:

```python
from app.factories import ServiceFactory

class UbuntuServer:
    
    services = ServiceFactory()

    def connect(self):
        self.establish_connection()
        return self
```

Boom. Done. Now our `UbuntuServer` has access to all of our services.

# Using It All Together

Let's go ahead and use these 2 factories in our application:

```python
from app.factories import ServerFactory

def show(self):
  user = User.find(1)
  user.server #== 'ubuntu'

  server = ServerFactory().make(user.server) #== <app.servers.UbuntuServer>
  server.connect()

  
  for service in ('postgres', 'nginx', 'rabbitmq'):
      server.services.make(service).install()
```

# The Future

Design patterns are useful for solving problems now and in the future. This pattern is useful because:

* supporting more servers is as simple as creating new servers.
* supporting more services is as simple as creating new services.

These two things can exist separately of each other and therefore can be scaled up or down separately of each other.