본문 바로가기
Delvelopment/DesignPattern

[Design Pattern] 싱글톤 패턴 (Singleton Pattern)

by 제제킴 2022. 7. 3.
반응형

**싱클톤 패턴(Singleton Pattern)**은 크래스 인스턴스를 하나만 만들고, 그 인스턴스로의 전역 접근을 제공한다.

싱글턴 패턴을 실제로 적용할 때는 클래스에서 하나뿐인 인스턴스를 관리핟로고 만들면 된다. 그리고 다른 어떤 클래스에서도 자신의 인스턴스를 추가로 만들지 못하게 해야한다. 인스턴스가 필요하다면 반드시 클래스 자신을 거치도록 한다.

싱글톤 패턴의 장점

  • 메모리 낭비 방지 가능.
  • 인스턴스를 활용함으로 써 속도 감정
  • 다른 클래스간의 데이터 공유가 가능

싱클톤 패턴의 문제점

  • 동시성 문제의 발생 (해결 가능)
  • 테스트가 어려움. 싱글톤 인스턴스는 자원을 공유하기 떄문에 매번 인스턴스 상태를 초기화 해야함
  • 싱글톤이 가지고 있는 역할이 많을 경우 결합도가 높아져 객체 지향 설계와 멀어짐. (OCP)
  • private 접근제어자를 가지고 있기 때문에 클래스의 분리가 어려움 (SRP, 단일 책임 원칙)

Sigleton 구현하기

  • Lazy Initializtion(늦은 초기화)
public class Singleton {

    private static Singleton uniqueInstance;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}
  • Eager Initialiaztion(이른 초기화)
    • 인스턴스를 시작하자마자 만든다.
    • 인스턴스를 수시로 생성하거나 관리하지 않고 처음부터 생성하는 방법.
public class StartSingleton {

    private static StartSingleton uniqueInstance = new StartSingleton();

    private StartSingleton() {
    }

    public static StartSingleton getInstance() {
        return uniqueInstance;
    }
}
  • DCL(Double-checked Locking)
    • DCL을 사용하면 인스턴스가 생성되어 있는지 확인한 다음 생성되어 있지 않았을 때만 동기화할 수 있습니다. 이러면 처음에만 동기화하고 나중에는 동기화하지 않아도 된다.
public class DclSingleton {

    private static volatile DclSingleton uniqueInstance;

    private DclSingleton() {
    }

    public static DclSingleton getInstance() {
        if (uniqueInstance == null) {
            synchronized (DclSingleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new DclSingleton();
                }
            }
        }
        return uniqueInstance;
    }
    
}
  • Enum Singleton
    • static final로 정의 (context 환경이 다른 APP 같은 경우는 그렇게 안전하진 않음)
public enum EnumSingleton {
    INSTANCE;

    public void aMethod(){
        // ...
    }
}
  • Lazy Holder (늦은 싱글톤)
    • 성능이 가장 뛰어나며 동기화 문제(Thread-safe)를 해결할 수 있음.
public class LazySingleton {

    private LazySingleton() {
    }

    private static class SingletonHolder {
        private static final LazySingleton INSTANCE = new LazySingleton();
    }

    public static LazySingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
    
}
  • 객체지향 원칙
    • 바뀌는 부분은 캡슐화 한다
    • 상속보다는 구성을 활용한다.
    • 구현보다는 인터페이스에 맞춰서 프로그래밍한다
    • 상호작용하는 객체 사이에서는 가능하면 느슨한 결합을 사용해야 한다
    • 클래스는 확장에는 열러 있어야 하지만 변경에는 닫혀 있어야 한다 (OCP)
    • 추상화된 것에 의존하게 만들고 구상 클래스에 의존하지 않게 만든다.
반응형

댓글