생성 (Creational) 패턴
다양한 상황에서의 객체의 생성 방식을 결정하는 디자인 패턴
주요 패턴으론 다음 사항들이 있다.
- 팩토리 메서드 (Factory Method)
- 추상 팩토리 (Abstract Factory)
- 빌더(Builder)
- 싱글톤(SingleTon) <- 이번 글에서 다룰 내용
- 프로토타입(Prototype)
- 템플릿메서드(TemplateMethod)
싱글톤 패턴 이란?
싱글톤 패턴(Singleton Pattern) 이란 클래스에 하나의 객체(인스턴스)로 모든 인스턴스와 공유하는 패턴
싱글턴 객체는 맨 처음 요청될 때만 초기화를 진행되며, 해당 인스턴스에 대해 전역 접근 지점이 존재함
객체 생성과 초기화
객체의 생성과 초기화에는 __new__와 __init__ 이라는 메서드가 사용
- __new__ : 객체의 생성 과정시 호출
- __init__ : 생성된 객체에 속성(property)을 추가 or 초기화 시 호출
__new__ 메소드에 대한 이해
사용자가 어떠한 목적을 가지고 클래스의 생성 과정에 관여하고 싶을 때, 직접 __new__ 메서드를 클래스에 추가함으로써 object 최상위 클래스의 __new__를 오버라이딩 하여 사용자의 __new__ 메소드가 호출되도록 한다. 만일 클래스에 __new__ 메소드를 오버라이딩 하여 선언하지 않으면, object 클래스의 __new__가 호출되어 객체가 생성됨
싱글톤 패턴을 사용하면 좋은 경우
- 여러 서비스의 로그를 동일한 로깅객체를 사용해 기록하는 경우
- 공유 리소스 관리 객체
- 애플리케이션 구성 설정 (config)
- 캐시
- DB 연결 모듈에 단일 객체로 작업 수행하는 경우 (말만 그렇지. 사실상 성능이 안나옴, 잘못된 정보)
코드
__new__ 메소드 재 정의 후 기존 객체 존재시, 신규 생성 X
활용되는 객체 속성은 '_instance' 변수로 관리
class Singleton(object):
# __new__, 이 __init__ 보다 먼저 실행됨
def __new__(cls, *args, **kwargs):
# _instance 속성 : Singleton 객체
if not hasattr(cls, "_instance"):
print("__new__ is called")
# 객체 생성 및 _instacne key로 바인딩
cls._instance = super().__new__(cls)
# _instance return
return cls._instance
def __init__(self, **kwargs):
cls = type(self)
# _init 속성 : Singleton 객체 존재 여부
if not hasattr(cls, "_init"):
print("__init__ is called")
self.db_settings = kwargs
cls._init = True
if __name__ == "__main__":
# 최초 DB Setting (+ Connection)
db = Singleton(db_name='mysql',db_port=3306)
# DB가 연결된 Object Singleton 객체로 소환
db_object1 = Singleton()
db_object2 = Singleton()
print(db)
print(db_object1)
print(db_object2)
출력 결과
최초 생성된 객체가 계속 사용되는 것을 확인 할 수 있다.
로그 관련
class Logger:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def log(self, message):
print(f"[LOG]: {message}")
if __name__ == "__main__":
logger = Logger()
# logger가 연결된 Object Singleton 객체로 소환
logger1 = Logger()
logger2 = Logger()
print(logger)
print(logger1)
print(logger2)
장단점
장점
- 신규 인스턴스 생성 비용이 줄어듬
단점
- 모듈간의 의존성이 높아짐 (이는 DI, Dependency Injection)을 통해 모듈간의 결합을 좀더 느슨하게 만들 수 있음
- decoupling을 통해 모듈 간의 의존성을 떨어뜨릴 수 있다.
참고 문헌
- https://refactoring.guru/design-patterns/singleton // 리팩 토링 구루루
- https://wikidocs.net/69361 // 위키독스 - 싱글톤 패턴
'소프트웨어 개발자 > 디자인패턴' 카테고리의 다른 글
[디자인패턴] 행동 패턴 - Command 패턴 (0) | 2024.05.01 |
---|---|
[디자인패턴] 행동 패턴 - 옵저버 패턴 (2) | 2024.05.01 |
[디자인패턴] 생성 패턴 - Prototype 패턴 (0) | 2024.03.31 |
[디자인패턴] 생성 패턴 - 빌더 (Builder) 패턴 (0) | 2024.03.30 |
[디자인패턴] 생성 패턴 - 팩토리 (Factory) 패턴 (1) | 2024.03.30 |