📗 Computer Science/Design Pattern
📗[CS/DesignPattern] 01. 싱글톤 패턴
혜덕hyeduck
2024. 5. 6. 19:27
💡 용어
- 라이브러리
- 공통으로 사용될 수 있는 특정 기능들을 모듈화한 것.
- 프레임워크에 비해 규칙에 있어 자유롭다.
- 프레임워크
- 공통으로 사용될 수 있는 특정 기능들을 모듈화한 것.
- 라이브러리에 비해 규칙이 좀 더 엄격하다.
디자인 패턴이란?
- 프로그랜 설계 시 직면한 문제들에 대해 객체 간 상호 관계들을 사용하여 해결할 수 있도록 정의한 일정의 규약
싱글톤 패턴
- 싱글톤 패턴(Singleton Pattern)이란 ?
- 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴
- 보통 데이터베이스 연결 모듈에서 많이 사용한다.
- 장점 : 인스턴스 생성 시 드는 비용이 줄어듦.
- 단점 : 의존성이 높아짐 → TDD 할 때 문제
- 보완 방법 → “의존성 주입 (DI, Dependency Injection)
- 중간에 의존성 주입자(dependency injector)를 통해 메인 모듈이 하위 모듈에 간접적으로 의존성을 주입할 수 있게 한다.
- 원칙 → “상위 모듈은 하위 모듈에서 어떠한 것도 가져올 수 없으며, 둘 다 추상화에 의존해야 한다.”
- 장점 : 테스팅, 마이그레이션이 수월. 구현시 추상화 레이어를 기반으로 구현체를 넣어주기 때문에 의존성 방향이 일관되며, 추론이 쉽다.
- 단점 : 클래스 수가 늘어나 복잡성이 증가될 수 있음, 런타임 페널티.
- 보완 방법 → “의존성 주입 (DI, Dependency Injection)
- Java 코드로 Singleton 구현하기
- private 생성자만 정의하여 외부 클래스로부터 인스턴스 생성 차단
- 싱글톤을 구현하는 클래스 내부 멤버 변수로 private static 객체 변수를 만들 것
- public static 메소드를 통해 외부에서 싱글톤 인스턴스에 접근할 수 있도록 함
- Java 코드로 Singleton 구현하기
- private 생성자만 정의하여 외부 클래스로부터 인스턴스 생성 차단
- 싱글톤을 구현하는 클래스 내부 멤버 변수로 private static 객체 변수를 만들 것
- public static 메소드를 통해 외부에서 싱글톤 인스턴스에 접근할 수 있도록 함
- 방법 1. 단순 메서드 호출
⇒ 그러나 멀티 스레드 환경에서 순차적으로 객체 생성이 안 이뤄질 수가 있다.
public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
- 방법 2. Synchronized
⇒ 1번 방법 보완을 위해 Synchronized 키워드로 잠금 ⇒ 즉, 최초 접근한 스레드가 getInstance() 메서드 호출시 접근하지 못하도록 lock을 걸어둔다. 그러나 이는 성능 저하 문제가 생길 수 있다.public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
- 방법 3. Static(정적 멤버)
⇒ 2번 문제 해결을 위해 등장. JVM 클래스 로딩과 동시에 싱글톤 인스턴스 생성. 그러나 필요없는 경우에도 호출하여 자원 낭비가 발생.
public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() {} public static synchronized Singleton getInstance() { return instance; } }
- 방법 4. Static(정적멤버) + Lazy Holder(중첩 클래스)
⇒ 보편적인 방법, 모듈이 필요한 경우에만 정적 멤버로 선언 → 자원 낭비 문제 해결
class Singleton { private static class singleInstanceHolder { private static final Singleton ISTANCE = new Singleton(); } public static Singleton getInstance() { return singleInstanceHolder.ISTANCE; } } // main에서 singleton.getInstance()로 호출
- 그외 3가지 방법이 더 존재함 → 추후 공부후 추가 예정