유틸리티로서 순수하게 사용되어질 오브젝트를 가지고 있다고 상상해보라. 이 오브젝트에는 어떠한
비지니스 로직도, 변경해야할 데이터도 포함되어 있지 않다.
단지 살아있는동안 프로그램의 다른 부분에서 필요로하는 기능들을 제공하면 된다. 당신이 이 오브젝트의 인스턴스를 필요할때마다 매번 새로 생성할 필요가 있을까?
정답은 "NO"이다. 싱글톤 패턴은 한 클래스로부터 생성된 인스턴스의 갯수를 컨트롤한다. 일반적으로 getInstance() 메소스로 정의한다. 개발자들이 언제든지 오브젝트의 인스턴스가 필요할때 이 메소드는 호출된다. 클래스에는 static property가 있다. getInstance()라고 불리는 이것은 인스턴스가 이미 존재
하는지를 먼저 체크한다. 만약 인스턴스가 존재한다면 이미 생성된 인스턴스를 반환하고, 그렇지 않을경우 새로운 인스턴스를 생성하고 static property에 저장한후, 새로 생성된 인스턴스를 반환한다.
자바스크립트에서는 아래와 같다.
function MyClass() {
this.myproperty = "hello world";
}
MyClass._instance_ = null; //define the static property
MyClass.getInstance = function(){
if (this._instance_ == null){
this._instance_ = new MyClass();
}
return this._instance_;
}
간단하게 클래스를 정의한후, static property인 _instance_ 를 정의한후, null로 할당한다. getInstance() 메소드(또한 static이다)는 static property를 체크하여 null인지 아닌지를 판단, null이라면 새로운
인스턴스를 생성하고 _instance_에 할당한다. 그리고나서 저장된 인스턴스를 함수의 반환인자로 넘긴다.
개발자들은 아래처럼 사용할 수 있다.
var oMyObject = MyClass.getInstance();
당신은 아래처럼 사용하는 개발자들을 추측할 수 있을 것이다.
var oMyObject = new MyClass();
당신은 팩토리 패턴을 사용하여 아래 처럼 수정할 수 있다.
function MyClass() {
if (Myclass.caller != MyClass.getInstance) {
throw new Error ("There is no public constructor for MyClass");
}
this.myproperty = "hello world";
}
싱글톤 패턴에 대한 중요 키포인트를 기억하라
1. 클래스의 인스턴스는 단 하나만 생성한다
2. 팩토리 패턴과는 달리, 싱글톤 패턴은 항상 확실한 클래스의 오브젝트만 생성한다.
3. 싱글톤 패턴은 당신이 생성한 어디에서든지 사용되어져야 한다.
이상으로 싱글톤 패턴에 대해서 알아봤습니다. 감이 오시는지 모르겠네요. 위에서도 간략하게 설명은 했지만 어떨때 싱글톤을 사용하면 좋을지에 대해서 다시 언급해보겠습니다.
우리에게 익숙한 팝업을 예로 들어보겠습니다. 우리는 아무때나 팝업객체를 호출하여 사용할 수
있습니다. var pop = new Popup() 이렇게 말이죠 (Popup객체는 임의의 객체)
우리가 보통 사용하듯 pop.show()를 한다면 팝업이 보여지겠죠. 하지만 팝업을 띄울때마다 new Popup()을 한다면 낭비가 아닐 수 없습니다. 팝업이란 한번 보여주고 닫힐 운명인데, 한번보여줄때 객체를
생성하고 필요없으면 소멸시키고, 다시 필요하면 또 생성하고....... 너무 낭비라고 생각치 않습니까? 지금이야 당장은 필요없으니까 없애고 필요할때 다시 생성하는게 더 효율적이지 않냐고 말할 수
있습니다. 그렇다면 아래의 상황의 경우 어떨까요?
동시에 다른 객체들로부터 팝업을 오픈시켜야 한다면.... 아래의 경우겠죠.
function A(){
....
var pop = new Popup()
....
}
function B(){
...
var pop = new Popup();
...
}
제가 물어 보겠습니다 A.pop과 B.pop이 동일한 객체로부터 생성된 인스턴스이므로 동일한 주소값을 가질까요? 즉, 같은 인스턴스이냐고 묻는 것입니다. 답은 아닙니다. 같은 객체로부터 인스턴스를 생성하였지만, 새로 객체를 생성하였으므로 인스턴스는 새로 작성이 됩니다. 못믿으시겠다구요? 그럼 이제부터
소스로서 살펴보도록 하겠습니다.
function Test(){
this.a = "aa";
this.b = function(){
alert(this.a);
}
}
var foo = new Test();
var bar = new Test();
if(foo == bar) alert('==');
else alert('!=');
위의 코드에서 alert로 실행되는 결과는 어떤것일까요? 답은 "!=" 입니다. 각은 객체로부터 생성
되었지만 각각의 인스턴스임을 나타내고 있습니다.
Test._instance = null;
Test.getInstance = function(){
if(this._instance == null) this._instance = new Test();
return this._instance;
}
function Test(){
if(Test.caller != Test.getInstance) throw new Error('There is no public constructor for MyClass');
this.a = "aa";
this.b = function(){
alert(this.a);
}
}
var foo = new Test();
위에서 배운것 처럼 싱글톤으로 객체를 호출할 준비가 되어있습니다.
그런데 new Test()로 객체를 생성하려고 하는군요. 그렇습니다. Error 객체에 의해 오류메세지가
출력됩니다.
제대로된 호출방법은 var foo = Test.getInstance(); 입니다. 그렇다면 질문을 드리겠습니다.
var foo = Test.getInstance();
var bar = Test.getInstance();
if(foo == bar) alert("==");
else alert("!=");
이렇게 되어있는 소스를 실행하면 어떤 결과가 나올거라 생각합니까? 답은 "=="가 출력됩니다.
이유는 위에서 설명드렸습니다.
싱글톤은 몇번을 호출해도 같은 인스턴스가 리턴되므로 객체를 재사용할 수 있고, 메모리 역시 절약할
수 있습니다. 이것이 싱글톤의 매력이겠지요. 여담이지만 자바에서의 싱글톤은 이렇게 구성하면
스레드에 의해 싱글톤이 깨질 수 있고 이를 방지하기위해 synchronized를 사용하고, 이를 더욱 확실히 하기위해 DCL(Double Checking Locking)기법을 이용하기도 합니다. 위의 예제는 아주 간단하게
만든것으로 이를 이용하고자 하시는 분은 적절히 상황에 맞게 수정하셔서 사용하시기 바랍니다.
이상으로 싱글톤 패턴에 대해서 마치고 다음 강좌를 준비하겠습니다.
posted by blankus
이 글의 트랙백 주소 :: http://www.blankus.net/trackback/18