---
title: "CP1 - Vending Machine (Factory) - Design Pattern From Simple Things"
description: "Beverages scattered across stores - too tiring to search each one. Learn how the Factory pattern centralizes object creation cleanly."
pubDate: "2022-10-29"
lang: "en"
slug: "cp1-vending-machine-factory-design-pattern-from-simple-things"
url: "https://hoangyell.com/cp1-vending-machine-factory-design-pattern-from-simple-things/"
author: "HoangYell"
categories: ["Software Craft"]
tags: ["design-patterns", "creational-patterns"]
heroImage: "https://raw.githubusercontent.com/HoangGeek/store/main/webp/8BPtbtB.webp"
---

_Vending Machine (Factory) is a **creational** design pattern:_
🖤🖤🖤🖤🖤

>Although widely used, `(Simple) Factory` is not part of the GoF Design Pattern. It's a term for a class creating objects without requiring any concrete classes.

>`Factory` is too vague for me, so I use `Vending Machine` instead! Vending Machine is the same as Factory, but it's more friendly :)

## What is Vending Machine?

Beverage Vending Machine is a store holding a variety of beverages(`Pepsi`, `Coke`, `Monster`)

Just enter beverage ID(`1`, `2`, `3`) to Beverage Vending Machine, then Beverage Vending Machine will return your beverage.

![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/201152775-2ec25d3c-b5a7-4b78-8320-d48dccb59023.webp)

## Why use Vending Machine?
It makes finding your beverage easier!

**Question:** _I hate the Beverage Vending Machine, but I want to buy a `Coke` right now because I'm bloating._

**Answer:** _You can find your `Coke` by searching in stores. If a store doesn't sell it, try to find it again by going to another store, try again until you find it_ 🙂

![Image](https://i.gifer.com/2oG7.gif)

## When to use Vending Machine?

**Question:** _When do I go to the `Beverage Vending Machine`?_

**Answer:** _When you need a beverage `Pepsi, Coke or Monster`, right?_

### Input:
  - Having a menu of beverages:
    - `Pepsi (ID = 1)`
    - `Coke (ID = 2)`
    - `Monster (ID = 3)`
  - Beverages are being sold.
  - Knowing the beverage you need to buy `Coke`.
```python
import abc

# Input 1: Having a menu of beverages:
class MENU:
    PEPSI = 1
    COKE = 2
    MONSTER = 3

class Beverage(metaclass=abc.ABCMeta):
    id = ""
    carbon_dioxide = 0

    # @abc.abstractmethod means: in the concrete class, The method have to re-defined
    @abc.abstractmethod
    def make_burp(self):
        return ""

# Input 2: Beverages are being sold.
class Pepsi(Beverage):
    id = MENU.PEPSI
    carbon_dioxide = 3

    def make_burp(self):
        return f"B{'U' * self.carbon_dioxide}RP"

# Input 2: Beverages are being sold.
class Coke(Beverage):
    id = MENU.COKE
    carbon_dioxide = 2

    def make_burp(self):
        return f"BU{'R' * self.carbon_dioxide}P"

# Input 2: Beverages are being sold.
class Monster(Beverage):
    id = MENU.MONSTER
    carbon_dioxide = 1

    def make_burp(self):
        return f"BURP"
```
### Expected Output:
  - Get a beverage `Coke`
  - Drink your beverage and make a burp `BURRP`
  - Get all carbonated_beverages
```shell
generate a beverage by id
<Coke object>
BURRP

generate all carbonated beverages
[<Pepsi object>, <Coke object>]
```
![Image](https://raw.githubusercontent.com/HoangGeek/store/main/webp/zo0BA2u.webp)

## How to implement Vending Machine?

### Non-Vending Machine implementation:
```python
if __name__ == "__main__":
    print("generate a beverage by id")
    beverage = None
    for beverage_cls in [Pepsi, Coke, Monster]:
        # Input 3: Knowing the beverage you need to buy.
        if MENU.COKE == beverage_cls.id:
            beverage = beverage_cls()
    # Expected Output 1: Get a beverage
    print(beverage)
    # Expected Output 2: Drink your beverage and make a burp
    print(beverage.make_burp())

    print("generate all carbonated beverages")
    carbonated_beverages = []
    for beverage_cls in [Pepsi, Coke, Monster]:
        if beverage_cls.carbon_dioxide > 1:
            carbonated_beverages.append(beverage_cls())
    print(carbonated_beverages)
```

### Vending Machine implementation:
```python
class BeverageVendingMachine:

    @property
    def subclasses(self):
        # [<class 'Pepsi'>, <class 'Coke'>, <class 'Monster'>]
        return Beverage.__subclasses__()

    @property
    def subclass_mapping(self):
        # {1: <class 'Pepsi'>, 2: <class 'Coke'>, 3: <class 'Monster'>}
        return {beverage.id: beverage for beverage in self.subclasses}

    def generate(self, key):
        subclass = self.subclass_mapping[key]
        instance = subclass()
        return instance

    @property
    def generate_carbonated_beverages(self):
        return [subclass() for subclass in self.subclasses if subclass.carbon_dioxide > 1]

if __name__ == "__main__":
    beverage_vending_machine = BeverageVendingMachine()

    print("generate a beverage by id")
    # Input 3: Knowing the beverage you need to buy.
    coke = beverage_vending_machine.generate(MENU.COKE)
    # Expected Output 1: Get a beverage
    print(coke)
    # Expected Output 2: Drink your beverage and make a burp
    print(coke.make_burp())
    
    print("generate all carbonated beverages")
    carbonated_beverages = beverage_vending_machine.generate_carbonated_beverages
    print(carbonated_beverages)
```

[Source Code](https://github.com/HoangYell/Design-Pattern-From-Simple-Things/blob/main/cp1_vending_machine.py)
