Python Design Pattern — Singleton

Cliffe
5 min readJun 9, 2019

--

이 포스팅은 파이썬 디자인 패턴 2/e 책을 참고로 쓴 글입니다.

일반적으로 Class는 여러 개의 객체를 생성할 수 있다. Singleton 패턴은 Class의 객체를 단 한 개만 허용하는 패턴이다. 이 패턴은 주로 로깅이나, DB 작업등에서 한 개의 객체만 허용하여 동일한 리소스에 대해 동시 요청으로 인한 충돌을 막을 때 사용된다.

싱글톤 패턴의 목적

  1. 클래스에 대한 단일 객체 생성
  2. 전역 객체 제공
  3. 공유된 리소스에 대한 동시 접근 제어

Singleton class는 객체를 생성할 때 이미 만들어진 객체가 없다면 새로 생성하고 그 이후부턴 동일한 객체를 반환하도록 구현한다.

__new__를 이용한 Singleton 구현

# python3에서는 object를 자동으로 상속받지만 2.x 버전과 호환을 위해 상속해 준다.
class Singleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance

python의 __new__ 함수를 이용하면 쉽게 구현할 수 있다. 객체가 아닌 클래스 내부에 instance가 존재하면 생성된 instance를 반환하고 없다면 새로운 객체를 생성하여 instance에 담고 반환한다. 여기서 __new__는새로운 인스턴스를 만들때 제일 처음으로 실행되는 메소드이다. __new__ 함수는 return을 하지 않으면 객체를 반환하지 않기 때문에 꼭 return을 해야한다.

print를 통해 어떻게 동작 하는지 비교

게으른 초기화(lazy initialization)를 이용한 Singleton 구현

사용할 수 있는 리소스가 제한적인 상황에서 게으른 초기화를 이용해서 꼭 필요한 시점에 객체를 생성할 수 있다.

class Singleton:
_instance = None
def __init__(self):
if not Singletone._instance:
print("__init__ method called but nothing is created")
else:
print("instance already created:", self.getInstance())

@classmethod
def get_instance(cls):
if not cls._instance:
cls._instance = Singleton()
return cls._instance
lazy initialization singleton

모노스테이트 싱글톤(Monostate Singleton)

싱글톤 패턴에 의하면 클래스의 객체는 하나만 존재해야 한다. 하지만 일부 개발자들은 객체 생성 여부보다 객체의 상태와 행위가 더 중요하다고 한다. 이는 하나의 객체만 존재해야 한다는 것에 너무 신경쓰지 않고 여러 객체 생성을 허용하더라도 상태를 공유해야한다는 것이다. 모노스테이트 싱글톤은 모든 객체가 같은 상태를 공유하는 패턴이다.

Monostate Singleton

파이썬은 __dict__에 객체의 상태를 저장한다. __dict__를 __shared_state로 지정해서 객체는 2개가 생기지만 각각의 __dict__는 같다. 모든 객체가 공유하는 상태가 된다.

싱글톤과 메타클래스 (Singleton and metaclass)

메타클래스는 클래스의 클래스이다. 클래스는 자신의 메타클래스의 인스턴스인 것이다. 메타클래스를 이용하면 이미 정의된 클래스를 통해 새로운 클래스를 생성할 수 있다.

Singleton and metaclass

싱글톤 패턴의 단점

  1. 전역 변수의 값이 실수로 변경된 것을 모르고 사용될 수 있다.
  2. 한 개의 객체만을 만들기 때문에 같은 객체에 대한 여러 개의 참조자가 생긴다.
  3. 전역 변수에 종속적인 모든 클래스 간 상호관계가 복잡해질 수 있다. 따라서 전역 변수 수정이 의도치 않게 다른 클래스에도 영향을 줄 수 있다.

더 좋은 의견이나 조언 및 오타 등등 수정 사항이 있으시다면 언제든 댓글 남겨주세요! 수정하도록 하겠습니다 :)

--

--