디자인 패턴 중 Singleton 패턴에 대해 설명합니다.
개념
오직 하나의 인스턴스 생성만 보장하며 전역 액세스 포인트를 제공하는 클래스 생성 패턴입니다. 공유자원, 메모리 낭비 등을 이유로 인스턴스 개수를 제한하고 싶을 때 사용합니다. 다음과 같은 장점이 있습니다.
- 전역에서 접근 가능한 공유자원에 하나의 인스턴스만 존재하도록 보장합니다.
- 전역 변수는 재할당이 가능하여 인스턴스를 저장하기 안전하지 않습니다. 안전하게 전역에서 접근 가능한 액세스 포인트를 제공합니다.
- 메모리 낭비를 방지합니다.
- 공유자원 접근을 제한할 수 있습니다.
자세히 살펴보겠습니다.
1. private 속성을 정의합니다. 해당 속성에 인스턴스를 저장하게 됩니다.
2. 클래스 생성자의 접근 제어자를 private로 설정하여 외부에서 접근을 제한합니다.
3. 전역에서 접근할 수 있는 get_instance 메소드를 정의합니다. 인스턴스를 얻기 위해서는 해당 메소드를 통해서만 얻을 수 있습니다.
4. get_instance 메소드에서 최초 호출 시 생성자를 통해 객체를 생성하여 private 속성에 저장 후 반환합니다. 두 번째 호출부터는 private 속성에 저장된 객체를 반환합니다.
코드 예시
파이썬은 생성자 호출 접근을 막을 수 없습니다. 그래서 다른 방법으로 싱글톤 패턴을 구현합니다. 싱글톤을 구현하는 몇 가지 방법을 소개합니다.
생성자 호출 제한
class SignletonA:
_instance: Optional["SignletonA"] = None
_init: bool = False
def __new__(cls, *args, **kwargs) -> None:
if not cls._instance:
cls._instance = super().__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self) -> None:
if not self._init:
self._init = True
# do initializing
print("init")
...
__new__ 생성자의 내부를 수정하여 생성자 호출을 제한하는 방법입니다. 최초 생성자 호출시 인스턴스를 생성하여 cls._instance에 저장하고 반환합니다. 이후 호출부터는 cls._instance를 반환합니다.
__new__ 호출이후 __init__ 메소드가 호출됩니다. self._init 속성을 통해 __init__ 메소드가 여러 번 수행되는 것을 막습니다.
데코레이터
def singleton_decorator(klass):
instances = {}
def get_instance(*args, **kwargs):
if klass not in instances:
instances[klass] = klass(*args, **kwargs)
return instances[klass]
return get_instance
@singleton_decorator
class SingetonB:
def __init__(self) -> None:
# do initializing
print("init")
...
클래스 데코레이터를 사용하여 생성자 호출을 제한하는 방법입니다. 최초 생성자 호출시 인스턴스를 생성한 후 instances 클로저 변수에 저장하고 반환합니다. 두 번째 호출부터는 instance 클로저 변수를 통해 반환합니다.
메타클래스
class SignletonMetaclass(type):
_instances = {}
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class SingletonC(metaclass=SignletonMetaclass):
def __init__(self) -> None:
# do initializing
print("init")
...
메타클래스를 정의하여 생성자 호출을 제한하는 방법입니다. 메타클래스의 __call__ 메소드를 오버라이드합니다.
참조
https://refactoring.guru/design-patterns/singleton
'객체 지향 > 디자인 패턴' 카테고리의 다른 글
디자인 패턴 - Bridge (0) | 2023.10.21 |
---|---|
디자인 패턴 - Adapter (0) | 2023.10.12 |
디자인 패턴 - Prototype (0) | 2023.10.09 |
디자인 패턴 - Builder (0) | 2023.10.09 |
디자인 패턴 - Abstact Factory (0) | 2023.10.05 |