본문 바로가기

DesignPattern

Singlton pattern

Singlton -pattern

클래스의 인스턴스가 단 하나만 필요 한 경우 사용한다.

– 지정한 클래스의 인스턴스가 절대로 1개밖에 존재하지 않는 것을 보증하고 싶을때

– 인스턴스가 1개밖에 존재하지 않는 것을 프로그램 상에서 표현하고 싶을때

요소를 1개 밖에 가지고 있지 않은 집합을 의미

Singleton 클래스

singleton은 static 필드로서 Singleton 클래스의 인스턴스에서 초기화된다.

Singleton 클래스의 생성자는 private 로 되어있다.

이것은 Singleton 클래스 외부에서 생성자의 호출을 금지하기 위해서이다.

만약 new Singleton() 이라는 식이 클래스 외부에 있더라ㄱ도 컴파일 시 에러가 발생

package Singleton;

public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){
System.out.println(“인스턴스 생성”);
}
public static Singleton getInstance(){
return singleton;
}
}

 

package Singleton;

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub

System.out.println(“start”);
Singleton obj = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();
if(obj==obj2){
System.out.println(“같은객체다”);
}

else{
System.out.println(“다른객체다”);
}
System.out.println(“End”);
}

}

SingletonUML

싱글톤 패턴은 역할만이 존재한다.

인스턴스를 얻기위한 static 메소드를 가지고 있다.

이 메소드는 언제나 동일한 인스턴스를 반환한다.

 

Why?

전제조건을 만드는 것이다 복수의 인스턴스가 서로 영향을 미치지 않기 위해서

getInstance를 호출할때 Singleton 클래스는 초기화 된다.

이때 static필드의 초기화가 이루어지고 유일한 인스턴스가 만들어진다

Example

 

멀티스레딩 문제 해결 방법

getInstance() 를 동기화시키기만 하면 멀티스레딩과 관련된 문제가 간단하게 해결된다. 그러나 동기화를 하게 되면 불필요한 오버헤드가 생기기 때문에 속도 문제가 발생할 수 있다. (대부분 그렇다.)

?
public class Singleton {
    private staticSingleton uniqueInstance;
    // 기타 인스턴스 변수
    private Singleton() {
    }
    // synchronized 키워드만 추가하면 두 스레드가 이 메소드를 동시에 실행시키는 일은 일어나지 않게 된다.
    public staticsynchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        returnuniqueInstance;
    }
    // 기타 메소드
}

* 더 효율적인 방법?

1. getInstance()의 속도가 그리 중요하지 않다면 그냥 내버려 둔다.

 – 메소드를 동기화하면 성능이 100배 정도 저하된다는 것을 기억해 두자.

 – 만약 getInstance() 가 애플리케이션에서 병목으로 작용한다면 다른 방법을 생각해봐야 한다.

 

2. 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버린다.

이런 접근법을 사용하면 클래스가 로딩될 때 JVM에서 Singleton의 유일한 인스턴스를 생성해 준다.

public class Singleton {
    private staticSingleton uniqueInstance = newSingleton();
    private Singleton() {
    }
    public staticSingleton getInstance() {
        returnuniqueInstance;
    }
}


 

 

3. DCL(Double-Checking Locking)을 써서 getInstance()에서 동기화되는 부분을 줄인다.

DCL(Double-Checking Locking)을 사용하면, 일단 인스턴스가 생성되어 있는지 확인한 다음, 생성되어 있지 않았을 때만 동기화를 할 수 있다.volatile키워드를 사용하여 멀티스레딩을 쓰더라도 uniqueInstance 변수가 Singleton 인스턴스로 초기화 되는 과정이 올바르게 할 수 있다. DCL은 자바 1.4 이하 버전에서 사용할 수 없다.

public class Singleton {
    private volatile staticSingleton uniqueInstance;
    private Singleton() {   }
    public static Singleton getInstance() {
        if (uniqueInstance ==null) {
            // 이렇게 하면 처음에만 동기화 된다
            synchronized(Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

출처:http://warmz.tistory.com/entry/Singleton-Pattern-%EC%8B%B1%EA%B8%80%ED%84%B4-%ED%8C%A8%ED%84%B4


'DesignPattern' 카테고리의 다른 글

Repository Pattern  (0) 2020.05.22
Clean Architecture 번역  (0) 2017.12.26
template pattern  (0) 2016.05.18
Iterator Pattern  (0) 2016.05.18
Factory pattern  (0) 2016.05.18