일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 폴더구조
- React Natvive
- 원복
- multipart upload
- 경우의 수
- React Native
- 창의충전소
- 자료구조
- 노마드코더
- 휴대폰 기기
- 해외 대외활동
- Project Bee
- 비트마스킹
- web view
- 이영직
- springboot
- 완전탐색
- Navigation
- bfs dfs
- 오블완
- 상속 관계 매핑
- 구현
- 백준 1992
- 버튼 활성화
- react
- FlatList
- service 테스트
- BFS
- 티스토리챌린지
- ReactNative
- Today
- Total
유미의 기록들
[디자인 패턴 -1] 싱글톤 패턴 (Singleton Pattern) 본문
싱글톤 패턴 (Singleton Pattern)
하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴
보통 하나의 클래스를 기반으로 여러 개의 개별적인 인스턴스를 만들 수 있지만, 싱글톤 패턴은 하나의 클래스를 기반으로 단 하나의 인스턴스를 만들어 전역변수와 같이 다른 모듈들이 공유하여 쓰도록 설계한다
보통 데이터베이스 연결모듈에 많이 사용한다
싱글톤 패턴 적용 전
import java.util.*;
import java.io.*;
public class Car{
Car(){
}
void powerOn(){
System.out.println("전원을 켰습니다");
}
void stop(){
System.out.println("멈췄습니다");
}
}
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException{
Car tesla1=new Car();
Car tesla2=new Car();
System.out.println(tesla1);
System.out.println(tesla2);
if(tesla1==tesla2){
System.out.println("같은 인스턴스입니다");
}else{
System.out.println("다른 인스턴스입니다");
}
}
}
실행결과
Main클래스에서 Car클래스의 인스턴스를 생성할 때 요청할 때마다 새로 생성되는 것을 알 수 있다
만약에 고객 트래픽이 초당 100개이면 100개의 인스턴스가 생성되고 소멸되어야 한다는 것이다
그럼 메모리 낭비가 발생하게 된다
💡 구현 원리
싱글톤 패턴을 적용하는 것은 간단하다
1. 외부 클래스에서 마구잡이로 new 생성자를 통해 인스턴스화 하는 것을 제한하기 위해 생성자 메서드에 private
키워드를 붙여준다
2. getInstance() 메서드에 new 생성자로 인스턴스화해주고, 만약 instance 변수가 null일 경우는 초기화하고, null이 아닐경우 이미 생성된 객체를 반환해서 사용한다
import java.util.*;
import java.io.*;
public class Car2{
//싱글톤 객체를 담을 변수
private static Car2 instance;
//getInstance()
public static Car2 getInstance(){
if(instance==null){
instance=new Car2();
}
return instance;
}
//private 생성자
private Car2(){
}
void powerOn(){
System.out.println("전원을 켰습니다");
}
void stop(){
System.out.println("멈췄습니다");
}
}
import java.util.*;
import java.io.*;
public class Main2{
public static void main(String[] args) throws IOException{
Car2 tesla1=Car2.getInstance();
Car2 tesla2=Car2.getInstance();
System.out.println(tesla1);
System.out.println(tesla2);
if(tesla1==tesla2){
System.out.println("같은 인스턴스입니다");
}else{
System.out.println("다른 인스턴스입니다");
}
}
}
실행결과
❓ 많이 사용하는 경우
객체가 리소스를 많이 차지하는 역할을 하는 무거운 클래스일때 적합
- DB에 접속하는 작업 (한번만 객체 생성하고 돌려쓰면 됨)
- 커넥션 풀, 스레드풀, 캐시, 로그기록….
⚠️ 단점
1. 단위 테스트 어려움
자원을 공유하고 있어서 서로 독립적이어야하는 단위 테스트를 하는데 문제가 된다. 독립적인 테스트가 진행이 되려면 전역에서 상태를 공유하고 있는 인스턴스의 상태를 매번 초기화해야 한다
2. 의존성이 높아진다 → 개방,폐쇄 원칙(OCP)위배
객체를 미리 생성한 뒤 필요한 경우 정적 메서드를 이용하기 때문에 클래스 사이의 의존성이 높아진다. 싱글톤의 인스턴스가 변경되면 해당 인스턴스를 참조하는 모든 클래스들을 수정해야 하는 문제가 발생한다
3. private 생성자 때문에 상속이 어렵다
상속을 통한 자식 클래스를 만들기 어렵다 → 다형성 적용 못함
4. 멀티스레드 환경에서 ThreadSafe하지 않는 문제점
여러 스레드가 동시에 접근하는 경우 문제가 발생한다
ThreadSafe
여러 스레드가 동시에 접근하는 경우 해당 애플리케이션에 어떠한 문제도 발생하지 않는것
반드시 싱글톤이 필요한 상황이 아니면 지양하는 것이 좋다. 안티패턴으로 불리기도 한다
따라서 싱글톤 패턴을 직접 구현하기 보다 스프링의 도움을 받아 위와 같은 문제점을 보완하면서 싱글톤 패턴의 장점을 누릴 수 있도록 이용하고 있다