Multiton Pattern
The Multiton pattern is a design pattern that generalizes the Singleton pattern by allowing multiple instances of a class, each identified by a unique key. This pattern is useful when you need to manage a limited number of instances that are distinguished by some attribute.
Import packages
| import sqlite3
import threading
from typing import Any, Dict, Type
|
Define class
| class Multiton(type):
_instances: Dict[int, Any] = {}
_locks: Dict[int, threading.Lock] = {}
_global_lock: threading.Lock = threading.Lock()
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
key = hash((cls, args, frozenset(kwargs.items())))
if key in cls._instances:
return cls._instances[key]
with cls._global_lock:
lock = cls._locks.setdefault(key, threading.Lock())
with lock:
if key not in cls._instances:
cls._instances[key] = super().__call__(*args, **kwargs)
return cls._instances[key]
@staticmethod
def drop() -> None:
Multiton._instances.clear()
Multiton._locks.clear()
|
Usage
| class APIClient(metaclass=Multiton):
def __init__(self, base_url: str):
self.base_url = base_url
client1 = APIClient("https://service1.com")
client2 = APIClient("https://service1.com")
client3 = APIClient("https://service2.com")
print(client1 is client2)
print(client1 is client3)
|
| class Config(metaclass=Multiton):
def __init__(self, env: str):
self.env = env
dev_config1 = Config("dev")
dev_config2 = Config("dev")
prod_config = Config("prod")
print(dev_config1 is dev_config2)
print(dev_config1 is prod_config)
|