관리 메뉴

밤 늦게까지 여는 카페

[디자인 패턴] 싱글톤(Singleton) 패턴이란 본문

디자인 패턴/생성 패턴

[디자인 패턴] 싱글톤(Singleton) 패턴이란

Jㅐ둥이 2022. 8. 23. 09:30
반응형

오늘 공부할 디자인 패턴은 싱글톤 패턴입니다.

1. 싱글톤 패턴이란

싱글톤 패턴을 적용한 클래스는 오직 하나의 객체만이 메모리 상에 존재한다는 것을 보장하고, 해당 클래스를 사용하는 어떠한 코드에서도 객체에 접근할 수 있도록 해주는 패턴입니다.

데이터베이스 연결 혹은 로컬 캐시 같은 기능을 구현할 때, 해당 기능을 담당하는 객체가 여러 개 생성된다면 예상치 못한 결과로 이어질 수 있습니다.
다른 생성 패턴들과 비교하면 보다 직관적인 이해가 가능한 것 같습니다. 바로 예시로 가시죠!

2. 예시

데이터를 저장하고 조회할 수 있는 간단한 LocalCache 객체를 예시로 들어보겠습니다. LocalCache 객체는 언제, 어디서 사용되더라도 동일한 데이터를 제공해줘야 한다는 요구사항이 있습니다. 이를 달성하기 위해서 LocalCache 클래스의 __new__, __init__ 메소드를 수정하였고 메모리 상에 하나의 LocalCache 객체만 존재하도록 구현했습니다.

"굳이 __new__, __init__을 수정하지 말고 전역 변수를 사용하면 되지 않나요?"

  • 전역 변수를 사용하는 것도 해결책이 될 수 있습니다. 하지만 누군가 규칙을 준수하지 않고, LocalCache 객체를 생성하게 된다면 시스템은 버그를 일으킬 수 있으므로 확실하게 __new__, __init__을 수정하였습니다.

"예제 코드에서 객체가 여러개 생성될 수 있는 틈이 보이는데요?"

  • 예리하시군요! 이 틈을 어떻게 없앨 수 있을까요?
class LocalCache:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            instance = super().__new__(cls)
            cls._instance = instance
        return cls._instance

    def __init__(self):
        cls = type(self)
        if not hasattr(cls, "_instance"):
            self.data = {}
    
    def get(self, *, key: str) -> str:
        return self.data.get(key)
    
    def set(self, *, key: str, val: str) -> str:
        return self.data[key] = val

if __name__ == "__main__":
    c1 = LocalCache()
    c1.set("test-key", "test-val")
    assert c1.get("test-key") == "test-val"

    c2 = LocalCache()
    assert c2.get("test-key") == "test-val"
반응형