싱글톤 패턴이란?
1) 어떠한 클래스가 최초한번만 메모리에 할당되고 그 메모리를 인스턴스로 만들어 재사용할 수 있는 패턴이다.
2) 하나의 인스턴스를 메모리에 등록하고 여러쓰리드에서 동시에 공유해서 사용할 수 있는 방법이다.
3) 주희할 점은 싱글톤 패턴을 만들땐 동시성에대해 주의를 고려해야한다.
- 싱글톤 패턴의 장점
1) 고정된 메모리 영역을 얻으면서 한번의 new 인스턴스만 사용하기 떄문에 메모리 낭비를 방지할 수 있다. / 인스턴스 생성시간을 줄일 수 있다.
2) 싱글톤 패턴으로 만들어진 인스턴스는 전역이기 때문에 다른 클래스인 인스턴스들과 데이터 공유가 쉽다.
3) 인스턴스가 한개만 존재하는것을 보증할 수 있다.
- 싱글톤 패턴의 단점
1) 싱글톤 패턴을 구현하려면 코드자체가 많이 필요하다.
2) 테스트가 힘들다. / 데이터를 공유하기 때문에 격리된 환경에서 수행되는 테스트가 온전히 수행되긴 힘들다
3) 자식클래스를 만들 수 없고, 메서드를 수정하는 등이 제한되어 유연성이 많이 떨어진다.
예시코드
// 싱글톤 패턴 객체 선언
public class Car {
private static Car instance;
private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
public static Car getInstance() {
if(instance == null) {
instance = new Car(); // instance가 없으면 static으로 Car를 선언한다.
}
return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다.
}
public void say() {
System.out.println("test Single");
}
}
// 싱글톤 패턴 접근
public class Test {
public static void main(String[] args) {
Car singleton1 = Car.getInstance();
Car singleton2 = Car.getInstance();
System.out.println(singleton1); // ch01.Car@5eb5c224
System.out.println(singleton2); // ch01.Car@5eb5c224
}
}
// 싱글톤 패턴 객체 선언
public class Car {
private static Car instance;
private static int num = 0; // 안에 변수를 설정하게 될경우
private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
public static Car getInstance() {
if(instance == null) {
instance = new Car(); // instance가 없으면 static으로 Car를 선언한다.
}
return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다.
}
public void count() {
num++;
}
}
외부에서 각기다른 스레드에서 위 count메소드를 사용하면 num의 데이터가 일관성있게 흘러가지 않는다.
위의 방법을 해결하기 위해선 2가지 방법을 적용할 수 있다.
public class Car {
private static Car instance = new Car(); // 초기에 인스턴스를 생성하게 된다면 다른 객체들은 getInstance를 통해 하나의 인스턴스를 공유할 수 있다.
private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
public static Car getInstance() {
return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다.
}
public void say() {
System.out.println("test Single");
}
}
public class Car {
private static Car instance;
private Car() { } // 생성자를 private로 선언해서 외부의 접근을 제한한다.
public static synchronzied Car getInstance() { // synchronzied를 적용하면 해결이 되지만 해당 방법은 성능 저하가 발생할 것이다.
if(instance == null) {
instance = new Car();
}
return instance; // 외부에서 클래스에 접근할 수 있는 getInstance메서드를 만든다.
}
public void say() {
System.out.println("test Single");
}
}
참고