싱글톤 패턴
이 글은 점프 투 자바 를 정리하여 작성하였습니다.
- 싱글톤 패턴은 단 하나의 객체만을 생성하게 강제하는 디자인 패턴 입니다.
- 즉, 클래스를 통해 생성할 수 있는 객체는 유일하도록 만드는 것이죠.
static
개념을 이해한다면 싱글톤을 이해하는 데 도움이 됩니다.
정적(Static) 변수와 메서드
변수/메소드 앞에 static
키워드를 붙여서 사용합니다.
static 변수
- 항상 값이 변하지 않는 경우,
static
키워드로 정적 변수로 사용하면 메모리 할당을 한번만 하게 되어 메모리 사용에 이점을 얻을 수 있습니다. - 아예 값을 상수로 사용하기 위해
final
를 붙여 값을 변경할 수 없도록 할 수도 있습니다. - 클래스 내의 변수를
static
으로 설정하면 같은 곳의 메모리 주소만을 바라보는 클래스 고유의 변수가 됩니다. - 모든 객체들이
static
변수의 값을 공유합니다.
static 메서드
static
변수와 마찬가지로 클래스 고유의 함수가 됩니다. 호출또한 클래스를 통해 호출할 수 있습니다.static
method 안에서는 인스턴스 변수 접근이 불가능합니다.static
변수만을 접근할 수 있습니다.static
method는 유틸리티 성 메소드를 작성할 때 많이 사용됩니다.예를 들어 "오늘의 날짜 구하기", "숫자에 콤마 추가하기"등의 메소드를 작성할 때에는 클래스 메소드를 사용하는 것이 유리합니다.
예제
다음은 "날짜"를 구하는 Util 클래스의 예입니다.
import java.text.SimpleDateFormat;
import java.util.Date;
public class Util {
public static String getCurrentDate(String fmt) {
SimpleDateFormat sdf = new SimpleDateFormat(fmt);
return sdf.format(new Date());
}
public static void main(String[] args) {
System.out.println(Util.getCurrentDate("yyyyMMdd"));
}
}
Util클래스의 getCurrentDate라는 스태틱 메소드(static method)를 이용하여 오늘의 날짜를(yyyyMMdd) 구하는 예제입니다.
위 클래스를 실행하면 오늘의 날짜가 출력됩니다.
싱글톤 패턴 (singleton pattern)
static
에 대한 이해를 바탕으로 싱글톤 패턴을 예제로 살펴보겠습니다.
예제
SingletonTest.java
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
// 생성자는 외부에서 호출못하게 private 으로 지정해야 한다.
}
public static Singleton getInstance() {
return instance;
}
public void say() {
System.out.println("hi, there");
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton.getInstance().say();
}
}
위의 코드는 싱글톤의 정의에 어긋나지 않게 new
를 이용해 여러개의 객체를 생성하는 것을 제한하려는 의도로 만들어진 코드입니다.
이 코드는 컴파일 에러가 발생합니다.
왜냐하면 Singleton 클래스의 생성자에 private 키워드로 외부 클래스에서 Singleton 클래스의 생성자로의 접근을 막았기 때문입니다.
이렇게 생성자를 private 으로 만들어 버리면 외부 클래스에서 Singleton 클래스를 new
를 이용하여 생성할 수 없게 됩니다.
그렇다면 Singletone 클래스의 객체는 어떻게 생성할 수 있을까요?
class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return new Singleton();
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
}
}
위와 같이 코드를 변경하면 이제 getInstance라는 static 메소드를 이용하여 Singleton 객체를 돌려 받을 수 있습니다.
하지만 getInstance를 호출 할 때마다 새로운 객체가 생성되게 되어 싱글톤이 아닙니다. 어떻게 해야 할까요?
class Singleton {
private static Singleton one;
private Singleton() {
}
public static Singleton getInstance() {
if(one==null) {
one = new Singleton();
}
return one;
}
}
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton1 == singleton2);
}
}
Singleton 클래스에 one 이라는 static 변수를 두고 getInstance 메소드에서 one 값이 null 인 경우에만 객체를 생성하도록 하여 one 객체가 단 한번만 만들어지도록 하면 됩니다.
싱글톤 패턴의 getInstance 메소드의 동작원리를 살펴보겠습니다.
최초 getInstance가 호출 되면 one이 null이므로
new
에 의해서 객체가 생성이 됩니다.이렇게 한번 생성이 되면 one은 static 변수이기 때문에 그 이후로는 null이 아니게 됩니다.
그런 후에 다시 getInstance 메소드가 호출되면 이제 one은 null이 아니므로 이미 만들어진 싱글톤 객체인 one을 항상 리턴하게 됩니다.
main 메소드에서 getInstance를 두번 호출하여 각각 얻은 객체가 같은 객체인지 확인해보면 "true"가 출력되어 같은 객체임을 확인 할 수 있습니다.
※ 위에서 예제로 든 싱글톤은 Thread Safe 하지는 않습니다. 쓰레드 환경에서도 안전한 싱글톤을 만드는 방법은 이 글 을 참고하시면 좋을 것 같습니다.
장점
- 고정된 메모리 영역 하나만을 사용하기 때문에 메모리 낭비를 방지할 수 있습니다.
- 싱글톤 인스턴스가 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있습니다. 따라서 다른 클래스 간에 데이터 공유가 쉽습니다.
단점
- 멀티스레딩 환경에서 싱글톤 인스턴스에 동시에 접근하는 것을 적절히 제어해야 합니다.
- 자원을 공유하고 있기 때문에 테스트에서 어려움이 있을 수 있습니다.
'SW > C# & WPF' 카테고리의 다른 글
[C#] Callback, Delegate (0) | 2021.06.01 |
---|---|
[WPF] Thread와 Dispatcher를 이용한 멀티스레딩 (0) | 2021.06.01 |
[C#] HTTP 통신 (0) | 2021.06.01 |
[C#] 추상클래스 & 인터페이스 (0) | 2021.05.28 |
[C#] 비동기식 프로그래밍 TAP (0) | 2021.05.19 |
Comment