Skip to content

Singleton Design Pattern

Video Lecture

Section Video Links
Singleton Overview Singleton Overview Singleton Overview Singleton Overview 
Singleton Use Case Singleton Use Case Singleton Use Case Singleton Use Case 
Python Dictionary Python Dictionary Python Dictionary Python Dictionary 

Overview

...Refer to Book, Videos or Medium Membership for extra content.

Singleton UML Diagram

Singleton UML Diagram

Source Code

...Refer to Book, Videos or Medium Membership for extra content.

./singleton/singleton_concept.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# pylint: disable=too-few-public-methods
"Singleton Concept Sample Code"
import copy

class Singleton():
    "The Singleton Class"
    value = []

    def __new__(cls):
        return cls

    # def __init__(self):
    #     print("in init")

    @staticmethod
    def static_method():
        "Use @staticmethod if no inner variables required"

    @classmethod
    def class_method(cls):
        "Use @classmethod to access class level variables"
        print(cls.value)

# The Client
# All uses of singleton point to the same memory address (id)
print(f"id(Singleton)\t= {id(Singleton)}")

OBJECT1 = Singleton()
print(f"id(OBJECT1)\t= {id(OBJECT1)}")

OBJECT2 = copy.deepcopy(OBJECT1)
print(f"id(OBJECT2)\t= {id(OBJECT2)}")

OBJECT3 = Singleton()
print(f"id(OBJECT1)\t= {id(OBJECT3)}")

Output

1
2
3
4
5
python ./singleton/singleton_concept.py
id(Singleton)   = 2164775087968
id(OBJECT1)     = 2164775087968
id(OBJECT2)     = 2164775087968
id(OBJECT3)     = 2164775087968

...Refer to Book, Videos or Medium Membership for extra content.

Example Use Case

...Refer to Book, Videos or Medium Membership for extra content.

Example UML Diagram

Singleton Use Case Diagram

Source Code

./singleton/client.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# pylint: disable=too-few-public-methods

"Singleton Use Case Example Code."

from game1 import Game1
from game2 import Game2
from game3 import Game3

# The Client
# All games share and manage the same leaderboard because it is a singleton.
GAME1 = Game1()
GAME1.add_winner(2, "Cosmo")

GAME2 = Game2()
GAME2.add_winner(3, "Sean")

GAME3 = Game3()
GAME3.add_winner(1, "Emmy")

GAME1.leaderboard.print()
GAME2.leaderboard.print()
GAME3.leaderboard.print()

./singleton/game1.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
"A Game Class that uses the Leaderboard Singleton"

from leaderboard import Leaderboard
from interface_game import IGame

class Game1(IGame):  # pylint: disable=too-few-public-methods
    "Game1 implements IGame"

    def __init__(self):
        self.leaderboard = Leaderboard()

    def add_winner(self, position, name):
        self.leaderboard.add_winner(position, name)

./singleton/game2.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
"A Game Class that uses the Leaderboard Singleton"

from leaderboard import Leaderboard
from interface_game import IGame

class Game2(IGame):  # pylint: disable=too-few-public-methods
    "Game2 implements IGame"

    def __init__(self):
        self.leaderboard = Leaderboard()

    def add_winner(self, position, name):
        self.leaderboard.add_winner(position, name)

./singleton/game3.py

1
2
3
4
5
6
"A Game Class that uses the Leaderboard Singleton"

from game2 import Game2

class Game3(Game2):  # pylint: disable=too-few-public-methods
    """Game 3 Inherits from Game 2 instead of implementing IGame"""

./singleton/leaderboard.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
"A Leaderboard Singleton Class"

class Leaderboard():
    "The Leaderboard as a Singleton"
    _table = {}

    def __new__(cls):
        return cls

    @classmethod
    def print(cls):
        "A class level method"
        print("-----------Leaderboard-----------")
        for key, value in sorted(cls._table.items()):
            print(f"|\t{key}\t|\t{value}\t|")
        print()

    @classmethod
    def add_winner(cls, position, name):
        "A class level method"
        cls._table[position] = name

./singleton/interface_game.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# pylint: disable=too-few-public-methods
"A Game Interface"

from abc import ABCMeta, abstractmethod

class IGame(metaclass=ABCMeta):
    "A Game Interface"
    @staticmethod
    @abstractmethod
    def add_winner(position, name):
        "Must implement add_winner"

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
python ./singleton/client.py
-----------Leaderboard-----------
|       1       |       Emmy    |
|       2       |       Cosmo   |
|       3       |       Sean    |

-----------Leaderboard-----------
|       1       |       Emmy    |
|       2       |       Cosmo   |
|       3       |       Sean    |

-----------Leaderboard-----------
|       1       |       Emmy    |
|       2       |       Cosmo   |
|       3       |       Sean    |

New Coding Concepts

Python Dictionary

In the file ./singleton/leaderboard.py,

4
5
    "The Leaderboard as a Singleton"
    _table = {}

The {} is indicating a Python Dictionary.

A Dictionary can be instantiated using the curly braces {} or dict()

The Dictionary is similar to a List, except that the items are key:value pairs.

The Dictionary can store multiple key:value pairs, they can be changed, can be added and removed, can be re-ordered, can be pre-filled with key:value pairs when instantiated and is very flexible.

Since Python 3.7, dictionaries are ordered in the same way that they are created.

The keys of the dictionary are unique.

You can refer to the dictionary items by key, which will return the value.

1
2
3
4
PS> python
>>> items = {"abc": 123, "def": 456, "ghi": 789}
>>> items["abc"] 
123

You can change the value at a key,

1
2
3
4
5
PS> python
>>> items = {"abc": 123, "def": 456, "ghi": 789}
>>> items["def"] = 101112 
>>> items["def"]
101112

You can add new key:value pairs, and remove them by using the key.

1
2
3
4
5
6
7
8
9
PS> python
>>> items = {"abc": 123, "def": 456, "ghi": 789}
>>> items["jkl"] = 101112
>>> items["jkl"]
101112
>>> items.pop('def')
456
>>> items
{'abc': 123, 'ghi': 789, 'jkl': 101112}

You can order a dictionary alphabetically by key

1
2
3
4
5
6
PS> python
>>> items = {"abc": 123, "ghi": 789, "def": 456}
>>> items
{'abc': 123, 'ghi': 789, 'def': 456}
>>> dict(sorted(items.items()))
{'abc': 123, 'def': 456, 'ghi': 789}

Summary

...Refer to Book, Videos or Medium Membership for extra content.