본문 바로가기
이론 공부 내용 정리

[CS스터디] Design Pattern - Singleton

by mazayong 2022. 12. 5.

--목차--

Singleton Pattern?

구현

-------

 

 

 

 

 

1. Singleton Pattern?

1) 정의

애플리케이션에서 인스턴스를 하나만 만들어 사용하기 위한 패턴.

(똑같은 인스턴스를 만들지 않고 기존의 인스턴스를 활용하는 것)

 

2) 목적

객체를 생성할 때마다 생기는 메모리 낭비 방지.

전역 인스턴스이므로 다른 클래스의 인스턴스들이 데이터 공유 가능.

 

3) 많이 사용하는 경우

공통된 객체를 여러 개 생성해서 사용해야 하는 상황.

DB : 커넥션 풀, 스레드 풀, 캐시, 로그 기록 객체

안드로이드 : 각 액티비티와 클래스마다 주요 클래스들을 일일히 전달하는게 번거로움.

인스턴스가 절대적으로 1개만 존재하는 것을 보증하고 싶을 때 사용.

 

4) 단점

개방-폐쇄 원칙에 의거.

(싱글톤 인스턴스가 혼자 너무 많은 일을 하거나, 많은 데이터 공유시 다른 클래스간 결합도가 높아져서 원칙 위반.)

(결합도가 높아지면 유지보수 어려움, 테스트 원활히 진행 불가)

멀티 스레드 환경에서 동기화 처리 없을 경우, 인스턴스 2개 생성 가능.

 

--> 반드시 싱글톤이 필요한 상황이 아니면 지양하는 것이 좋음.

++

개방-폐쇄 원칙(OCP) : 소프트웨어 객체(클래스, 모듈, 함수)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 함.

(기능이 변하거나 확장 가능하지만 해당 기능의 코드는 수정하면 안됨.)

객체의 모듈화와 정보 은닉의 올바른 구현을 추구, 객체간 의존성을 최소화해 코드 변경에 따른 영향력 낮추기 위함.

 

 

 

 

 

2. 구현 (멀티스레드 환경에서의 구현)

1) Lazy initialization

private static으로 인스턴스 변수 생성

private로 생성자를 만들어 외부에서의 생성 막음.

synchronized 동기화를 사용해 스레드를 안전하게 만듦.(큰 성능저하 발생하므로 권장하지 않음)

 

2) Lazy initialization + Double-checked Locking

조건문으로 인스턴스 존재 여부를 확인한 다음 2번째 조건문에서 synchronized로 동기화를 시켜 인스턴스 생성.

스레드를 안전하게 만들면서, 처음 생성 이후에는 synchronized를 실행하지 않아 성능저하 완화.

완벽한 방법은 아님.

 

3) Initialization on demand holder idiom(holder에 의한 초기화)

클래스 안에 클래스(holder)을 두어 JVM의 클래스 로더 매커니즘과 클래스가 로드되는 시점 활용.

동기화 사용 안하는 방법이 없는 이유 : 개발자가 직접 동기화 문제에 대한 코드 작성시 프로그램 구조 복잡+비용 문제+코드 부정확

JVM의 클래스 초기화 과정에서 보장되는 원자적 특성을 이용해 싱글톤의 초기화 문제에 대한 책임을 JVM에게 떠넘기는 것 활용.

선언된 인스턴스는 static이어서 클래스 로딩 시점에서 1번만 호출, final을 이용해 다시 값이 할당되지 않도록 함.

(가장 많이 사용되는 싱글톤 클래스 사용법)

 

 

 

 

참조

https://gyoogle.dev/blog/design-pattern/Singleton%20Pattern.html

https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/DesignPattern

https://blog.itcode.dev/posts/2021/08/14/open-closed-principle