2014년 1월 13일 월요일

Singleton = 특정클래스의 인스턴스를 하나만 생성하는 방법

특정 클래스의 인스턴스를 하나만 생성해야 하는 경우가 있다.

왜 그런상황이 생기는지 회원가입, 로그인을 예로 들어보자.
회원DB 클래스의 인스턴스를 회원가입과 로그인에서 
각각 A인스턴스, B인스턴스로 따로 생성하였다. 이때 회원 이모씨가 서비스에 가입하였다. 이모씨의 회원가입은 A인스턴스가 실행하였다. 그런데 이모씨는 제대로 로그인이 되는지 확인하기 위해 잠깐 로그아웃을 하고 다시 로그인을 시도하였다. 그런데 이때 사용된 B인스턴스에는 이모씨의 정보가 추가되어 있지 않다. 이모씨는 로그인에 실패하여 어플을 지워버렸다.
이 상황에서 B인스턴스 입장에서는 A인스턴스를 통해서 회원가입이 일어났는지 확인할 길이 없다. 한 클래스에서 여러 인스턴스를 생성하면서 발생하는 문제다.

이 경우 반드시 하나의 인스턴스만을 생성하여 해당 인스턴스를 하상 호출하여 사용하도록 하면 문제가 해결된다. 

이때 사용되는 하나의 인스턴스만을 사용하도록 하는 '디자인 패턴'을 Singleton이라고 한다.


Singleton은 
1. 클래스 내에 인스턴스를 생성하고

2. 생성자를 private으로 선언하여 
외부에서 해당 인스턴스를 생성하지 못하도록 한다.

3. 외부에서 해당 인스턴스를 사용하려고 할 경우 getInstance()를 이용하여 
클래스 내에 이미 선언된 인스턴스만을 사용하도록 한다.

고로 해당 클래스 내에서 static으로 생성된 인스턴스만 사용되는 것이다.
프로그램내의 모든 곳에서 해당 클래스의 특성 인스턴스만 사용한다.


간단한 코드 예시

public class MemberManager {
1.   private static MemberManager instance = null;
    

2.   private MemberManager() {
        this.members = this.getMembersFromFile();
    }
3.   public static MemberManager getInstance() {
// 아직 인스턴스가 생성되지 않았을 경우 최초 생성한다.
        if(MemberManager.instance == null)
            MemberManager.instance = new MemberManager();
        return MemberManager.instance;
    }
}



+추가
private static MemberManager instance로 선언하는 이유가 뭐냐.
그냥 private으로 선언하면 어떻게 됨?

-> 3.에서 변수 instance를 사용하는데 (그냥 private이면)static이 아니므로
1) 객체를 생성하지 않고 사용하면 컴파일이 되지않는다.
2) 객체를 생성하면 해당 static 메소드를 호출할때마다 객체를 생성하기 때문에
하나의 특정 객체만을 생성하고 사용하는 싱글톤이 더이상 아니게 된다.

++추가 static 메소드, 변수는 왜 쓰는 건가요?
-> 클래스 자체에 관련해서 설명이 필요한 경우 사용한다.
ex) 사용자가 로그인을 할때마다 사용자 객체를 생성하는 클래스가 있다.
현재 사용중인 사용자 목록을 가져오는 메소드가 필요한 경우
static으로 선언하여 사용한다. 어떤 특정 객체에 연관되지 않고 사용할 메소드이기 때문.
물론 일반 메소드로 선언하여 사용할 수도 있으나, 특정 객체를 지정하여 메소드를 호출하여야 하고, 부자연스럽다.
결론 : static 메소드, 변수가 필요한 이유는 어느 객체에도 속하지 않는 행위, 데이터의 처리가 필요한 경우?

댓글 없음:

댓글 쓰기