ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Design Pattern] 싱글톤 패턴 (Singleton Pattern)
    공부/디자인 패턴 2020. 2. 23. 18:41

    싱글톤 패턴이란?

    개발을 진행하다 보면 클래스 내에서 인스턴스를 1개만 생성해야 하는 경우가 있습니다. 이럴 때, 해당 클래스를 사용하는 여러 곳에서 인스턴스를 계속 생성하다 보면 불필요하게 메모리 낭비를 야기 시킵니다. 이럴 때 싱글톤 패턴을 사용하면 불필요한 메모리 낭비를 방지하고 해당 클래스의 인스턴스를 바로 호출할 수 있습니다.

    싱글톤 패턴에서는 생성자를 클래스 자체에서만 접근할 수 있도록 private와 같이 접근 제어자를 통해 제어해야 합니다. 만약 생성자를 열어두면 해당 클래스를 다른 부분에서 인스턴스화 시킬 수 있기 때문입니다. 접근 제어자로 막는 것과 더불어 수정이 되지 않도록 막아야 합니다. 만약 인스턴스 생성 이후, 수정이 가능하다면 해당 클래스의 인스턴스를 Null로 초기화 시켜버릴 수 있기 때문입니다.

    이러한 내용의 구현은 사전에 초기화 하는 방법과 늦은 초기화가 있습니다.

    Eager initialization (사전 초기화)

    클래스가 호출될 때, 인스턴스를 생성하는 방법입니다. 해당 방법은 위 문제들을 해결할 순 있지만, 인스턴스를 사용하지 않아도 생성하기 때문에 효율은 낮습니다.

    Lazy initialization (늦은 초기화)

    인스턴스를 실제로 사용할 시점에서 생성하는 방법입니다. 문제로는 두 스레드가 동시에 싱글톤 인스턴스에 접근하고 생성이 안 된 것을 확인하여 생성한다면 중복으로 생성할 수 있다는 문제가 있습니다. 하지만 인스턴스를 실제로 사용하지 않으면 생성하지 않으므로 사전 초기화 방법보단 효율이 좋습니다.

    예시

    class Singleton {
        static final Singleton instance = new Singleton();
    
        private Singleton() {
        }
    
        public Singleton getInstance() {
            return instance;
        }
    }


    파이썬에서..

    파이썬에서도 싱글톤 패턴은 유용하게 사용할 수 있습니다. 

    class SingletonType(type):
        def __call__(cls, *args, **kwargs):
            try:
                return cls.__instance
            except AttributeError:
                cls.__instance = super(SingletonType, cls).__call__(*args, **kwargs)
                return cls.__instance
    
    
    class Calculator(metaclass=SingletonType):
        def calc_exam(self, *score):
            return sum(score)
    


    from pattern import Calculator
    
    
    calculator1 = Calculator()
    score1 = calculator1.calc_exam(1,2,3,4,5)
    print(score1)
    
    
    calculator2 = Calculator()
    score2 = calculator2.calc_exam(1,2,3,4,5)
    print(score2)
    
    
    print(calculator1 is calculator2)
    
    
    # 15
    # 15
    # True


    위 방법은 늦은 초기화 방법으로 인스턴스화할 때, 해당 인스턴스가 메모리에 올라가게 되고 다음 호출에서는 메모리에 있는 인스턴스를 가져다 사용하는 방식입니다. 


    파이썬에서는 만약 인스턴스를 하지 않는다고 보장이 된다면 클래스 자체로 싱글톤과 같은 효과를 볼 수 있습니다.

    class Calculator:
        @classmethod
        def calc_exam(cls, *score):
            return sum(score)


    from pattern import Calculator
    
    calculator1 = Calculator
    
    score1 = calculator1.calc_exam(1,2,3,4,5)
    
    calculator2 = Calculator
    score2 = calculator2.calc_exam(1,2,3,4,5)
    
    
    print(calculator1 is calculator2)


    댓글