ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 싱글톤 패턴(Singleton Pattern)
    디자인 패턴 2021. 10. 28. 20:58

    💡 싱글톤 패턴이란?

    GOF의 디자인 패턴중 '생성' 패턴에 속하는 패턴으로, 클래스에서 오직 '한 개'의 인스턴스만 인스턴스 화 할 수 있도록 규제하는 디자인 패턴

     

    📗 싱글톤 패턴의 장점

    1. 클래스가 오직 한 개의 인스턴스만 가지고 있다고 확신 할 수 있다.
    2. 인스턴스 수를 제한 할 수 있다.
    3. 전역 변수에 액세스 함으로써 손쉽게 접근 할 수 있다.

     

    📖 함께 쓰일 수 있는 패턴들

    1. Abstract pattern, Factory Method, Builder, Prototype
    2. State pattern, Facade Pattern

     

    📖 전역변수보다 싱글톤 패턴이 나은 점

    1. 불필요한 변수로 Global namespace를 훼손하지 않는다.
    2. 지연 할당과 초기화를 지원함으로써 사용하든 안하든 리소스를 소모하는 전역변수와 달리 싱글턴 패턴은 효율적으로 자원 활용이 가능하다.

     

    ⚠️ 싱글톤 패턴의 단점

    • 싱글톤 패턴은 안티 패턴에 속한다. 안티패턴이란 프로그램을 만들 때 비효율적이고 역효과가 나타날 수 있는 패턴을 말한다.
    • 싱글톤 패턴은 주로 global하게 선언되는데, 이는 프로그램의 결합도를 증가시켜 유닛 테스트를 하기 힘들게하고, 싱글톤 객체에 의존하는 객체가 불필요한 제약을 따르게 한다.
    • 싱글톤 패턴을 사용하면, 싱글톤 패턴을 적용한 객체는, 객체를 오직 '하나'만 생성해야 하는 규약과 자신이 원래 하던 일 두가지를 하게 되므로 SRP(Single responsible Principle)도 위반한다.

     

    🚀 구현

    일반적으로 싱글턴은 클래스의 모든 '생성자'를 private으로 선언하고, 생성된 객체를 참조할 수 있는 변수를 리턴하는 static 메소드를 사용하는 방식으로 구현된다.

    class SingletonTest {
    
        @Test
        void singletonTest() {
            SingletonObject singletonObject1 = SingletonObject.getInstance();
            SingletonObject singletonObject2  = SingletonObject.getInstance();
            System.out.println(singletonObject1 == singletonObject2);
        }
    }
    
    class SingletonObject {
    
        private static SingletonObjectinstance;
    
        private SingletonObject() {}
    
        public static SingletonObject getInstance() {
            if(instance== null) {
                        instance= new SingletonObject();
            }
    
            return instance;
        }
    }
    

    output

     

     

    멀티 스레드 환경에서 Race Condition을 막기 위해서 다음과 같이 구현 할 수도 있다.

    class SingletonTest {
    
        @Test
        void singletonTest() {
            SingletonObject singletonObject1 = SingletonObject.getInstance();
            SingletonObject singletonObject2  = SingletonObject.getInstance();
            System.out.println(singletonObject1 == singletonObject2);
        }
    }
    
    class SingletonObject {
    
        private static volatile SingletonObject instance;
    
        private SingletonObject(){};
    
        public static SingletonObject getInstance() {
            if(instance == null) {
                synchronized (SingletonObject.class) {
                    if(instance == null) {
                        instance = new SingletonObject();
                    }
                }
            }
    
            return instance;
        }
    }

    output2

     

    위의 코드에서 'volatile'과 'synchronized '키워드가 어색해서 검색해봤다.

    volatile은 변수의 값을 '캐시'가 아닌 메인 메모리에 저장하라는 것이고 synchronized 키워드는 멀티 스레드 환경에서 race condition을 막기 위해 사용하는 것으로, 한 스레드가 synchronized 메소드에 들어가면 'lock'을 걸어 다른 스레드가 들어오지 못하게 하는 메소드라고 한다. 둘 다 멀티스레드 환경에서 읽기/쓰기를 할 경우 Race Condition을 방지하기 위해 사용하는 메소드인듯하다.

    '디자인 패턴' 카테고리의 다른 글

    Decorator Pattern  (0) 2022.02.08
    Observer Pattern  (0) 2022.02.03
    Strategy Pattern  (0) 2022.02.02
    Facade Pattern  (0) 2021.10.27
    디자인 패턴 개요  (0) 2021.01.06

    댓글

Designed by Tistory.