싱글톤 패턴

싱글톤 패턴이란 클래스의 인스턴스화를 하나의 객체로 제한하는 패턴이다.

일단 어떻게 만들면 좋을 지 간단하게 만들어 보자.

Object literal

이 자체로는 유용하진 않지만 객체 리터럴로 간단하게 만들 수 있다.

var Person = {
	name: 'hxxtae',
	age: 20,
	greeting: function () {
		return `Hi! ${this.name}`;
	},
};

유용하지 않은 이유는 이 코드가 불변성을 제공하지 않기 대문에 언제든지 재정의될 수 있기 때문이다. 조금만 더 개선해 보자.

const Person = {
	name: 'hxxtae',
	age: 20,
	greeting: function () {
		return `Hij ${this.name}`;
	},
}

Object.freeze(person);
export default person;

*const로 변수 선언을 하였기 때문에 제할당 할 수 없으며, Object.freeze를 통해 메서드나 속성을 변경/추가할 수 없게 만들었다.*

(만약 기존 속성을 변경하게 해줄 목적이라면 Object.seal를 사용해도 되지만, 직접 변경의 방법을 열어주는 것보단 setter 를 제공해 주는 것이 더 좋다.)

대부분의 객체 리터럴로 만들면 읽기 쉽고 간결하다. 하지만 과거부터 사용해 오던 전통적인 객체지향의 구조화된 방법들을 적용할 수가 없는 단점이 있다. 일반적으로 객체 지향에서 많이 사용하는 class로는 조금 있다가 수정해 보자.

물론, Object.assign() 을 통해 객체 리터럴을 복사하여 사용한다면 불변성은 깨지며, Object.freeze() 메서드의 경우 “얕은 동결” 이기 때문에 인스턴스의 속성 자체가 object 값을 가지고 있다면 불변성을 깨지게 된다. 이런 경우를 전부 대응하고 나열한다면 글이 길어질 것 같아 일단 싱글톤 패턴의 구현이라는 것에만 초점을 두고 게속 이야기를 해보자.

IIFE + Closure (모듈 패턴)

즉시 실행 함수와 클로저를 통해서도 싱글톤과 유사하게 구현할 수 있다. 별건 아니지만 타입 스크립트도 추가해보았다.

interface IPerson {
	name: string;
	age: number;
	greeting: VoidFunction;
}

const Person = (function () {
	let instance: IPerson | undefined;

	function createInstance(): IPerson {
		return {
			name: 'hxxtae',
			age: 20,
			greeting: function () {
				return `Hi! ${this.name}`;
			},
		};
	}

	return {
		getInstance: function () {
			if(instance === undefined) {
				instance = createInstance();
			}
			return instance;
		},
	};

})();

const hxxtae1 = Person.getInstance();
const hxxtae2 = Person.getInstance();

console.log(hxxtae1 === hxxtae2); // true