본문 바로가기
파이썬/파이썬의 디자인 패턴 공부

02 싱글톤 디자인 패턴

by David.Ho 2023. 12. 18.
728x90
반응형
싱글톤 디자인 패턴 개요

싱글톤 디자인 패턴은 글로벌하게 접근 가능한 하나의 객체를 제공하는 패턴이다.

 

싱글톤 디자인 패턴은 주로 하나의 인스턴스를 공유하여 로깅, 데이터베이스 관련 작업, 프린터 스풀러 등과 같은 동일한 리소스에 대한 동시 요청의 충돌을 방지하는데 사용된다.

ex) 1) DB작업 수행 시 일관성 유지를 위해 하나의 데이터베이스 객체를 사용하는 경우
      2) 로그를 기록하는 작업 시 여러 서비스의 로그를 하나의 로그 파일에 순차적으로 동일한 로깅 객체를 사용해 적제하는 경우

 

[싱글톤 디자인 패턴의 목적]

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

 

 

싱글톤 패턴 UML 다이어그램

위와 같은 다른 언어의 경우 생성자(Constructor)를 private로 선언하고 객체를 초기화하는 static 함수를 만들어 간단하게 싱글톤 패턴을 구현할 수 있지만 파이썬에서는 private에 대한 기능을 제공하지 않기 때문에 다른 방법으로 구현을 해야 한다.

즉, 핵심은 첫 호출에 객체가 생성되고 클래스는 동일한 객체를 계속 반환한다.

 

파이썬 싱글톤 패턴 구현

1. 하나의 Singleton 클래스 인스턴스를 생성한다.

2. 이미 생성된 인스턴스가 있다면 재사용한다.

[위의 코드 설명]

(1) __new__ 함수(python 전용 특수 생성자)를 오버라이드해 객체를 생성한다.

(2)__new__함수는 s객체가 이미존재하는지 확인하고 hasattr 함수(해당 객체가 명시한 속성을 가지고 있는지 확인하는 파이썬 함수)는 cls객체가 instance 속성을 가지고 있는지 확인(false, true 반환)하다.
즉, 클래스 객체가 이미 존재하는지 확인하는 과정이다.

(3) s1 객체를 요청하면 hasattr()은 이미 객체가 생성됐음을 확인하고 해당 인스턴스(0x0000021BB4599EB0)을 반환한다.

 

'__new__ ' 메서드:
- '__new__'는 객체가 생성될 때 호출되는 특수한 메서드입니다.
- 클래스의 인스턴스를 만들기 위해 호출되며, 첫 번째 인수로 클래스 자체('cls')를 받습니다.
- 객체가 생성되는 단계에서 호출되므로, 객체의 생성 및 초기화 이전에 실행됩니다.
- 주로 클래스의 새 인스턴스를 생성하고 반환하는 역할을 합니다. 새로운 객체가 만들어지고 반환된 후에 '__init__' 메서드가 호출됩니다.
- '__new__' 메서드를 오버라이드할 때는 주로 불변 객체(immutable object)를 만들거나 객체 생성의 과정을 커스터마이징할 때 사용됩니다.
'__init__' 메서드:
- '__init__' 메서드는 객체가 생성된 후에 호출되는 메서드입니다.
- '__new__'가 반환한 인스턴스를 인자로 받아 객체의 초기화를 담당합니다.
- 초기화 작업을 수행하여 객체의 속성을 설정하거나 초기값을 할당합니다.
- 'self'를 첫 번째 인자로 받으며, 이를 통해 객체의 속성을 초기화하거나 설정할 수 있습니다.
- 객체가 이미 '__new__'에 의해 생성되었기 때문에, '__init__' 메서드는 초기화를 위한 작업을 처리합니다.

 

super()함수:
파이썬에서 부모 클래스의 메서드를 서브 클래스에서 호출할 때 사용하는 내장 함수입니다. 상속 관계의 자식 클래스에서 부모 클래스의 메서드를 호출해야 할 때 주로 활용됩니다.


super()를 사용하여 부모 클래스의 메서드를 호출하면, 메서드 해결 순서(Method Resolution Order, MRO)를 따라 부모 클래스의 메서드를 호출합니다. 이를 통해 다중 상속 시에도 적절한 순서로 메서드를 호출할 수 있습니다.
class ParentClass:
    def some_method(self):
        # 부모 클래스의 메서드
        pass

class ChildClass(ParentClass):
    def some_method(self):
        # 부모 클래스의 메서드 호출
        super().some_method()
        # 자식 클래스의 추가적인 작업
        pass​


파이썬 3에서는 보통 super()를 사용할 때 인자를 넘겨주지 않아도 됩니다. 파이썬은 현재 클래스와 인스턴스를 기반으로 알맞은 메서드를 찾아 호출합니다. 하지만 파이썬 2에서는 super()를 사용할 때 클래스와 인스턴스를 명시적으로 전달해주어야 합니다.

class ParentClass:
    def some_method(self):
        print("ParentClass의 메서드")

class ChildClass(ParentClass):
    def some_method(self):
        super().some_method()  # 인자 없이 super() 사용
        print("ChildClass의 메서드")

# 사용 예시
child = ChildClass()
child.some_method()
class ParentClass(object):  # 파이썬 2에서는 명시적으로 object를 상속받아야 함
    def some_method(self):
        print("ParentClass의 메서드")

class ChildClass(ParentClass):
    def some_method(self):
        super(ChildClass, self).some_method()  # 클래스와 인스턴스 명시적으로 전달
        print("ChildClass의 메서드")

# 사용 예시
child = ChildClass()
child.some_method()
728x90
반응형

댓글