The Singleton Design Pattern
싱글톤 디자인 패턴 개요
실글톤 디자인 패턴은 글로벌하게 접근 간으한 단 한 개의 객체만을 하여하는 패턴
DB, 프린트 스풀러, app 등 동일한 리소스에 대한 요청의 충돌을 막기 위해 한개의 인스턴스만 사용
- 싱글톤 디자인 패턴의 목적
- 클래스에 대한 단일 객체 생성
- 전역 객체 제공
- 공유된 리소스에 대한 동시 접근 제어
- 코드 - singleton.py 설명
__new__ 함수를 오버라이드해 객체를 생성한다.
__new__ 함수는 객체가 이미 존재하는지 확인하고 hasattr 함수는 cls 객체가 instance속석을 가지고 있는지 확인한다.
hasattr 함수 : 해당 객체가 명시한 속성을 가지고 있는지 확인하는 파이썬 함수
게으른 초기화(Lazy instantiation)
게으른 초기화는 싱글톤 패턴의 한 종류
게으른 초기화는 인스턴스가 꼭 필요할 때 생성한다.
사용할 수 있는 리소스가 제한적인 상황일 때 객체가 꼭 필요한 시점에서 생성하는 방식
lazy_instantiation.py 참조
모듈 싱글톤
파이썬의 임포트 방식 때문에 모든 모듈은 기본적으로 싱글톤이다.
모노스테이트 싱글톤 패턴 (The Monosstate Singleton Pattern)
알렉스 마르텔리(Alex Martelli)는 상태를 공유하는 인스턴스가 필요하다고 주장
즉, 객체 생성 여부보다 객체의 상태와 행위가 더 중요하다고 이야기함
모노스테이트 싱글톤 패턴은 모든 객체가 같은 상태를 공유하는 패턴이다.
- code
- 파일 1 __author__ = 'Chetan'
class Borg:
shared_state = {"1":"2"}
def __init(self):
self.x = 1
self.dict = self.__shared_state
pass
b = Borg()
b1 = Borg()
b.x = 4
서로 다른 객체
print("Borg Object 'b': ", b)
print("Borg Object 'b1': ", b1)
같은 내용을 출럭함 (같은 상태 공유)
print("Object State 'b':", b.dict)
print("Object State 'b1':", b1.dict)
- 파일 2 - new method 이용하는 방법
author = 'Chetan'
class Borg(object):
shared_state = {}
def _new(cls, args, *kwargs):
# 객체 인스턴스를 생성하는 메소드
obj = super(Borg, cls).new(cls, args, *kwargs)
obj.dict = cls._shared_state
return obj
### 싱글톤과 메타클래스
메타클래스 : 클래스의 클래스 ?? -> 클래스는 자신의 메티클래스 인스턴스 <br>
객체 생성시 클래스는 메타클래스가 정의 <br>
name(클래스 명), base(베이스 클래스), dict(속성 값)
author = 'Chetan'
class MetaSingleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Logger(metaclass=MetaSingleton):
pass
logger1 = Logger()
logger2 = Logger()
print(logger1, logger2)
클래스는 메타클래스가 정의한다.
싱글톤 패턴의 단점
1. 전역 변수의 값 변경 시 다른 클래스에게도 영향을 준다.
2. 같은 객체에 대한 여러 참조자가 생길 수 있다.
State desgom pattern (상태 디자인 패턴)
1. 상태 디자인 패턴 개요
행위 디자인패턴은 객체의 역할에 중점을 둔다
객체는 내부 상태에 따라 여러 행위를 캡슐화 한다. 상태 패턴은 런타임에 객체의 행위를 변경
- 상태 디자인 패턴의 구성 요소
State : 객체의 행위를 캡슐화하는 인터페이스
ConcreteState : State 인터페이스를 구현하는서브클래스.
Context : 사용자가 선택한 인터페이스를 정의. 특정 상태의 구현한 ConcreteState 서브클래스의 인스턴스를 가지고 있다.
author = 'Chetan'
from abc import abstractmethod, ABCMeta
class State(metaclass=ABCMeta):
@abstractmethod
def doThis(self):
pass
class StartState (State):
def doThis(self):
print("TV Switching ON..")
class StopState (State):
def doThis(self):
print("TV Switching OFF..")
class TVContext(State):
def __init__(self):
self.state = None
def getState(self):
return self.state
def setState(self, state):
self.state = state
def doThis(self):
self.state.doThis()
context = TVContext()
context.getState()
start = StartState()
stop = StopState()
context.setState(stop)
context.doThis()
-
위 코드에서의 역할
State : Handle() 추상 메소드를 정의하는 인터페이스
-
ConcreteState가 구현
ConcreteState : State 설정에 따라 실행될 각 Handle() 메소드를 구현
Context : 사용자의 요청을 넘겨받는 클래스
2. 상태 디자인 패턴의 장단점
-
상태 디자인 패턴의 장점
상황에 따라 if else와 같은 조건부 연산을 줄일 수 있다.
다형성(Polymorphic) 구현이 쉬우며 새로운 상태를 쉽게 추가할 수 있다
상태 관련 행위가 모두 ConcreteState 클래스에 있으므로 응집도(Cohesion)가 높아진다.
새로운 ConcreteState 클래스를 추가해 쉽게 신규 기능을 구현할 수 있다.
-
상태 디자인 패턴의 단점
클래스 남발(Class Explosion)이 나타단다.
새로운 행위는 ConcreteState를 새로 추가하면 되지만 Context 클래스도 맞게 수정해줘야 한다.