The Singleton Pattern

Singleton 패턴은 Creational 패턴들과 같은 그룹에 속하지만, "non-creational" 패턴의 확장적인 면이 있다. 프로그래밍에서 클래스의 인스턴스를 하나만을 갖게 해야 할 경우가 있다. 예를 들어 우리의 시스템은 오직 하나의 윈도우 메니져나 프린트 스풀러를 가질 수 있다. 

유일하게 하나의 인스턴스를 갖는 클래스를 만드는 가장 간단한 방법은 static 변수를 클래스에 포함시키는 것이다. static 변수는 유일한 인스턴스의 하나이고, 인스턴스의 수는 문제가 되지 않는다.
static boolean instance_flag = false;

문제는 생성된 인스턴스가 성공적인지 아닌지를 어떻게 찾는가 인데 이것은  생성자가 반환을 하지 않기 때문이다. 한가지 방법은 생성의 성공여부를 체크하는 메소드를 호출하는 것이다. 그리고 메소드들은 static 변수로부터 유도된 값을 반환한다. 이 방법은 세련되지 못하고 오류들을 발생할 수 있는 경향이 있지만, .................................

좀더 나은 방법은 하나 이상 인스턴스가 생성될 때 예외(Exception)를 발생하는 클래스를 생성하는 것이다. 이런 경우에 우리 자신의 예외 클래스를 생성해 보자 : 

class SingletonException extends RuntimeException {

	//new exception type for singleton classes
	public SingletonException() {
		super();
	}
     //-----------------------------------------------
	public SingletonException(String s) {
		super(s);
	}
}

이 새로운 예외 타입은 특별하게 새로 작성된 내용없이 부모의 클래스를 호출할 것 뿐이다. 그러나  PrintSpooler의 인스턴스를 시도할 때 우리가 잡아야만 하는 예외의 타입을 컴파일러는 우리 자신이 이름을 지은 예외 타입으로 경고하는 편리함이 있다. 

Throwing the Exception

PrintSpooler 클래스의 골격을 작성해 보자; 프린팅 메소드들은 생략하고 단지 정확한 Singleton 패턴의 구현에만 초점을 둘 것이다. 
class PrintSpooler {

	//this is a prototype for a printer-spooler class
	//such that only one instance can ever exist
	static boolean instance_flag = false;	//true if 1 instance
	
	public PrintSpooler() throws SingletonException {
		if (instance_flag)
			throw new SingletonException("Only one spooler allowed");
		else 
			instance_flag = true;	//set flag for 1 instance
		
		System.out.println("spooler opened");
	}
	
	//----------------------------------------------
	
	public void finalize() {
		instance_flag = false;	//clear if destroyed
	}
}

Creating an Instance of the Class

지금까지 우리는 PrintSpooler 클래스에서 Singleton 패턴을 생성하였다. 이제 그 것을 어떻게 사용하는 지 알아보자. 예외를 발생시킬 지도 모르는 모든 메소드들에 대하여 try - catch 블럭안에 에워싸야한다는 것을 기억하자. 

public class SingleSpooler {

	public static void main(String[] args) {
		PrintSpooler pr1, pr2;
		
		//open on spooler--this should always work
		System.out.println("Open one spooler");
		try {
			pr1 = new PrintSpooler();
		}
		catch(SingletonException e) {
			System.out.println(e.getMessage());
		}
		
		//try to open another spooler -- should fail
		System.out.println("Open two spoolers");
		try {
			pr2 = new PrintSpooler();
		}
		catch(SingletonException e) {
			System.out.println(e.getMessage());
		}
	}
}

그리고 나서, 프로그램을 실행시키면 아래와 같은 결과를 얻을 수 있다.

            ##########0* 

Static Classes as Singleton Patterns

표준 자바 라이브러리에는 이미 Singleton 클래스의 종류가 있다:Math 클래스 . 이 클래스는 final로 선언되어 있고 모든 메소들이 static 으로 선언되어 있다. 이는 확장될 수 없음을 의미한다. Math 클래스의 목적은 sin이나 cos 처럼 일반적으로 사용되는 수학적인 함수들을 포장해 놓은 것이다. 

우리는 Singleton 클래스를 final 클래스로 하여 Singleton 패턴을 구현할 수 있다. 우리는 Math 클래스 처럼 어떤 인스턴스도 만들 수 없고, final 클래스에 존재하는 static 메소드들을 직접 호출해서만 사용할 수 있다. 
final class PrintSpooler {
	//a static class implementation of Singleton pattern
	static public void print(String s) {
		System.out.println(s);
	}
}

//==============================

public class StaticPrint {
   	public static void main(String argv[]) {
	      PrintSpooler.print("here it is");
	}
}
final 클래스 접근의 이점중의 하나는 try-catch 블럭을 쓸 필요가 없다는 거다. 이 이점은 만약 우리가 Singleton 상태를 중지하고자 한다면 예외 처리 스타일의 구조보다 더 쉽다는 것이다. 

Creating Singleton Using a Static Method

Design Patterns에 제안된 또 하한의 접근은 인스턴스들의 자취를 유지하고 유출하는 static 메소드를 사용하여 Singleton을 생성하는 것이다. 하나 이상의 인스턴스가 만들어 지는 것을 막기 위해 그 클래스의 static 메소드에서만 생성될 수 있는 private 의 생성자를 만든다.

class iSpooler {

	//this is a prototype for a printer-spooler class
	//such that only one instance can ever exist
	static boolean instance_flag = false; //true if 1 instance

	private iSpooler() {
	}

	static public iSpooler Instance() {
   		if (! instance_flag) {
			instance_flag = true;
			return new iSpooler();
		}
		else
			return null;      
	}
	//-------------------------------------------
	public void finalize() {
		instance_flag = false;
	}
}                                                        

이렇게 함으로써 얻는 주요 이점은 singleton이 이미 존재한다면 예외처리에 대해서는 신경 쓰지 않아도 된다는 것이다. 또, iSpooler 클래스의 인스턴스를 만드려 한다면 생성자가 private로 선언되어 있어 컴파일시 실패하게 될 것이다.

Other Consequences of the Singleton Pattern

  1. Singleton을 하위 클래스로 만드는 것은 어려울 수 있는데, 이것은 상위의 Singleton 클래스가 생성되지 않았을 때만 작동하기 때문이다.
  2. 우리는 적당하고 의미있는 곳에서의 작은 수의 인스턴스를 허용하는 Singleton으로 쉽게 바꿀 수 있다.

'Development > 패턴자료' 카테고리의 다른 글

[펌] The Strategy Pattern  (0) 2011.08.13
[펌] The State Pattern  (0) 2011.08.13
[펌] The Proxy Pattern  (0) 2011.08.13
[펌] The Prototype Pattern  (0) 2011.08.13
[펌] The Observer Pattern  (0) 2011.08.13
안정적인 DNS서비스 DNSEver DNS server, DNS service
Posted by 키르히아이스
,