반응형
개요
- 글로벌하게 접근 가능한 하나의 객체를 제공하는 패턴
- 로깅, 데이터베이스 관련 작업 등 동일한 리소스에 대한 동시 요청의 충돌을 방지하기 위해 하나의 인스턴스를 공유하는 작업에 주로 사용
싱글톤 패턴을 사용하는 경우
- 데이터의 일관성 유지 위해 DB에 작업을 수행하는 하나의 데이터베이스 객체가 필요한 경우
- 여러 서비스의 로그를 한 개의 로그파일에 순차적으로 동일한 로깅 객체를 사용해 남기는 경우에 적합
코드 구현
class Singleton:
def __new__(cls): # (1)
if not hasattr(cls, "instance"): # (2)
cls.instance = super().__new__(cls)
return cls.instance
s1 = Singleton()
s2 = Singleton()
print('s1: ', s1) # s1: <__main__.Singleton object at 0x000001A4B84A51D0>
print('s2: ', s2) # S2: <__main__.Singleton object at 0x000001A4B84A51D0>
print('singleton: ', s1 is s2) # True
(1) __new__ 메소드
- __new__ 메소드는 객체를 생성할 때 호출됨 (__init__ 메소드는 객체에 속성을 추가할 때 호출됨)
- 호출순서 : __new__ -> __init__ 메소드
(2) 클래스 객체에 instance 속성이 있는지 확인
- instance 속성이 없으면 super() 인 object 클래스의 __new__ 메소드를 호출하여 instance 속성 생성 후 반환
- super() : 부모클래스 객체를 반환하는 함수. 상속받는 클래스가 없는경우 object 클래스를 상속받음
Singleton 클래스 인스턴스를 2개 생성했지만 각각의 주소가 같으므로 둘은 같은 인스턴스를 가리키고 있음
게으른 초기화
- 싱글톤 패턴을 기반으로 하는 초기화 방식
- 인스턴스를 꼭 필요할 떄 생성
- 모듈을 import 할 때 필요하지 않는 시점에 실수로 미리 객체를 생성하는 경우 방지
class Singleton:
__instance = None
def __init__(self):
if not Singleton.__instance:
print('__init__ method called')
else:
print("Instance already created:", self.get_instance())
@classmethod
def get_instance(cls):
if not cls.__instance:
cls.__instance = Singleton()
return cls.__instance
if __name__=='__main__':
s = Singleton() # __init__ method called 초기화만하고 객체 생성 X
print('object created', Singleton.get_instance()) # 객체 생성
# object created <__main__.Singleton object at 0x00000183220C51D0>
s1 = Singleton()
# Instance already created: <__main__.Singleton object at 0x00000246DBAB51D0>
- 객체를 생성하기 위해서는 Singleton.getInstance() 호출
모듈 싱글톤
- 파이썬은 모든 모듈을 기본적으로 싱글톤으로 import함.
- 아래 코드를 통해 싱글톤 여부 확인 가능
# Singleton.py
shared_variable = "shared variable"
# module1.py
import singleton
print('singleton in module_1: ', singleton.shared_variable)
singleton.shared_variable += "(modified by module_1)"
print('shared_variable was modified in module_1)
# module2.py
import singleton
print('singleton in module2: ', singleton.shared_variable)
위 3개의 .py 파일을 만든 후 모두 import
# test.py
import module1
# singleton in module1: shared variable
import module2
# singleton in module2: shared variable(modified by module_1)
- singleton 모듈을 module1.py, module2.py 에서 각각 import
- module1.py 에서 수정된 singleton 모듈의 변수(shared_variable)가 module2.py에서도 수정된 채로 확인됨
Reference
1) 책 "파이썬 디자인 패턴 2/e"
2) https://wikidocs.net/69361
반응형