728x90
1. 싱글톤 패턴 개념
싱글톤 패턴은 객체 지향 디자인 패턴 중 하나로, 특정 클래스의 인스턴스가 단 하나만 생성되도록 보장하는 패턴이다.
이 패턴을 사용하면 전역적으로 접근 가능한 객체를 만들어 공유 자원이나 설정 객체 등을 효율적으로 관리할 수 있다.
2. 싱글톤 패턴 특징
- 유일한 인스턴스 : 해당 클래스의 인스턴스는 하나만 존재한다.
- 전역적 접근 : 어디서든지 이 인스턴스에 접근할 수 있다.
- 게으른 초기화 : 인스턴스가 필요한 시점에 생성된다.
- 스레드 안정성 : 다중 스레드 환경에서도 안전하게 사용될 수 있다.
3. 싱글톤 패턴 사용 이유
싱글톤 패턴을 사용하지 않아 특정 클래스의 인스턴스가 하나 이상 생성된다면, 여러 문제점이 발생할 수 있다.
- 자원 낭비 : 메모리와 다른 시스템 리소르를 불필요하게 낭비한다.
- 데이터 불일치 : 여러 인스턴스 간 데이터 공유가 안되어 데이터 불일치가 발생할 수 있다.
- 상태관리 어려움 : 상태를 일관되게 유지하기 어려워진다.
- 충돌 발생 : 동일한 자원을 동시에 수정하는 등 충돌이 발생할 수 있다.
- 유지보수 어려움 : 여러 인스턴스 간 동작을 추정하고 디버깅하기가 어려워진다.
4. 싱글톤 패턴 구현 방법
public class MySingleton {
// 2. 정적 변수로 인스턴스를 관리
private static MySingleton instance;
// 1. 생성자를 private으로 선언하여 외부에서의 인스턴스 생성을 막음
private MySingleton() {
// 생성자 코드
}
// 3. 게으른 초기화를 통해 인스턴스를 반환(더블체크락을 통해 성능저하를 최소화한다.)
public static MySingleton getInstance() {
if (instance == null) { //인스턴스 생성되어있는지 확인, 생성되어있다면 바로 현재 인스턴스 반환.
synchronized (MySingleton.class) {//자바의 동기화 메커니즘: synchronized를 실행하면 즉시 객체 잠금일어남.
if (instance == null) { //다수의 스레드가 동시에 null체크 통과해도 한 스레드만 인스턴스 생성하도록하기 위함
instance = new MySingleton();
}
}
}
return instance;
}
// 싱글톤 클래스의 다른 메서드들
public void doSomething() {
// 기능 구현
}
}
public class Main {
public static void main(String[] args) {
MySingleton mst = MySingleton.getInstance(); //getInstance()메서드를 이용하여 인스턴스를 얻는다.
}
}
5. 싱글톤 패턴 사용 예제 코드(회사 출결관리 프로그램)
import java.util.HashMap;
import java.util.Map;
// 출결 관리 클래스 (Singleton)
public class AttendanceManager {
private static AttendanceManager instance; // 1. 정적 변수로 인스턴스를 유지
// 출결 기록을 저장할 자료구조
private Map<String, Boolean> attendanceRecords;
private AttendanceManager() {
attendanceRecords = new HashMap<>(); // 2. 생성자를 private으로 선언하여 외부에서 인스턴스 생성을 막음
}
// 3. 게으른 초기화를 통해 인스턴스를 반환
public static AttendanceManager getInstance() {
if (instance == null) { // 4. 더블 체크 락을 활용한 인스턴스 생성
synchronized (AttendanceManager.class) {
if (instance == null) {
instance = new AttendanceManager();
}
}
}
return instance; // 5. 생성된 인스턴스 반환
}
// 출근 기록
public void markAttendance(String employeeId) {
attendanceRecords.put(employeeId, true);
System.out.println("Employee " + employeeId + " has marked attendance.");
}
// 퇴근 기록
public void markDeparture(String employeeId) {
attendanceRecords.put(employeeId, false);
System.out.println("Employee " + employeeId + " has marked departure.");
}
// 출결 조회
public void checkAttendance(String employeeId) {
Boolean isPresent = attendanceRecords.get(employeeId);
if (isPresent != null && isPresent) {
System.out.println("Employee " + employeeId + " is present.");
} else {
System.out.println("Employee " + employeeId + " is absent.");
}
}
}
Main
public class Main {
public static void main(String[] args) {
// 출결 관리 인스턴스 얻기
AttendanceManager manager = AttendanceManager.getInstance();
// 직원 출근 기록
manager.markAttendance("E001");
manager.markAttendance("E002");
// 직원 퇴근 기록
manager.markDeparture("E001");
// 출결 조회
manager.checkAttendance("E001");
manager.checkAttendance("E002");
manager.checkAttendance("E003"); // 존재하지 않는 직원
}
}
728x90
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] 제네릭(generic)의 개념과 활용법 (1) | 2023.12.19 |
---|---|
[과제] UML에 맞게 싱글톤 패턴 적용하기 (0) | 2023.12.18 |
[Java] 업캐스팅(Upcasting)과 다운캐스팅(Downcasting) (0) | 2023.12.18 |
[Java] StringBuilder 사용 이유 & 주요 메서드 (0) | 2023.12.17 |
[과제] 상속, 오버라이딩 (1) | 2023.12.16 |