싱글톤 패턴(Singleton Pattern)

wannabeking·2022년 3월 24일
0

디자인 패턴

목록 보기
1/14

싱글톤 패턴(Singleton Pattern)

싱글톤 패턴이란?

  • 어떤 클래스가 최초 한번 메모리를 할당하고 해당 메모리에 여러 레퍼런스를 생성하여 사용하는 디자인 패턴

  • static을 사용하여 인스턴스 생성

  • 싱글톤 패턴을 사용하지 않는 경우

    // Dog.java
    public class Dog {
        private String name;
        
        public Dog(String name) {
            this.name = name;
        }
        
        public void bark() {
            System.out.println(name + ": " + "멍!");
        }
    }
    // Main.java
    public class Main {
        public static void main(String[] args) {
            Dog dog1 = new Dog("dog1");
            Dog dog2 = new Dog("dog2");
            
            dog1.bark();
            dog2.bark();
            
            if (dog1.equals(dog2)) {
                System.out.println("dog1 & dog2 => 같습니다.");
            } else {
                System.out.println("dog1 & dog2 => 다릅니다.");
            }
        }
    }

    실행 결과


    dog1: 멍!
    dog2: 멍!
    dog1 & dog2 => 다릅니다.

    • dog1과 dog2는 다른 이름을 가질 수 있으며 같은 인스턴스가 아님
    • 즉, 메모리에 Dog이 2번 할당

  • 싱글톤 패턴을 사용하는 경우

    // SingleDog.java
    public class SingleDog {
        private static final SingleDog instance = new SingleDog("singleDog");
        private static String name;
        
        private SingleDog(String name) {
            this.name = name;
        }
        
        public static SingleDog getInstance() {
            return instance;
        }
        
        public void changeName(String name) {
            this.name = name;
        }
        
        public void bark() {
            System.out.println(name + ": " + "멍!");
        }
    }
    // Main.java
    public class Main {
        public static void main(String[] args) {
            SingleDog singleDog1 = SingleDog.getInstance();
            SingleDog singleDog2 = SingleDog.getInstance();
            
            singleDog1.changeName("singleDog1");
            singleDog2.changeName("singleDog2");
            
            singleDog1.bark();
            singleDog2.bark();
            if (singleDog1.equals(singleDog2)) {
                System.out.println("singleDog1 & singleDog2 => 같습니다.");
            } else {
                System.out.println("singleDog1 & singleDog2 => 다릅니다.");
            }
        }
    }

    실행 결과


    singleDog2: 멍!
    singleDog2: 멍!
    singleDog1 & singleDog2 => 같습니다.

    • singleDog1과 singleDog2는 다른 이름을 가질 수 없으며 같은 인스턴스
    • 즉, 메모리에 singleDog이 1번 할당 & 해당 메모리에 2개 인스턴스 생성

모든 소스코드는 여기에서 확인할 수 있다.



Java에서 싱글톤 패턴 구현

  • Eager Initialization
    • 가장 간단한 형태의 구현 방법
    • 어플리케이션에서 해당 인스턴스를 사용하지 않더라도 클래스 로딩 단계에서 인스턴스 생성
public class Singleton {
    private static final Singleton instance = new Singleton();
    
    private Singleton(){}
 
    public static Singleton getInstance(){
        return instance;
    }
}

  • Lazy Initialization
    • 나중에 인스턴스를 초기화하는 방법 => 무의미한 인스턴스 생성 방지
    • 멀티 쓰레드 환경에서 동시에 getInstance()를 호출하면 예상치 못한 결과 생김
    • 여러 인스턴스가 생성된다면 싱글톤 패턴이 아니기 때문에 싱글 쓰레드 환경에서만 사용
public class Singleton {
    private static Singleton instance;
    
    private Singleton(){}
    
    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

  • Bill Pugh Singleton Implementaion
    • Bill Pugh가 고안한 방식으로, inner static class를 사용하는 방식
    • helper 클래스는 getInstance()가 호출 되었을 때 비로소 인스턴스 생성 => 무의미한 생성 방지
    • 클래스가 로드될때 인스턴스가 생성되므로 멀티 스레드 환경에서도 안전
public class Singleton {
    private Singleton(){}
    
    private static class SingletonHelper{
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance(){
        return SingletonHelper.INSTANCE;
    }
}


싱글톤 패턴의 단점

  • 확장에는 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다는 '개방-폐쇄 원칙' 어길 수 있음
  • 개발이 진행됨에 따라 싱글톤 클래스가 복잡해질 수 있음
  • 멀티 쓰레드 환경에서 동기화처리의 부재로 여러 개의 인스턴스가 생길 수 있음


profile
내일은 개발왕 😎

0개의 댓글