반응형

개요

  • 글로벌하게 접근 가능한 하나의 객체를 제공하는 패턴
  • 로깅, 데이터베이스 관련 작업 등 동일한 리소스에 대한 동시 요청의 충돌을 방지하기 위해 하나의 인스턴스를 공유하는 작업에 주로 사용

 

싱글톤 패턴을 사용하는 경우

  1. 데이터의 일관성 유지 위해 DB에 작업을 수행하는 하나의 데이터베이스 객체가 필요한 경우
  2. 여러 서비스의 로그를 한 개의 로그파일에 순차적으로 동일한 로깅 객체를 사용해 남기는 경우에 적합

 

코드 구현


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

 

 

반응형

+ Recent posts