컨텐츠를 불러오는 중...
싱글턴은 클래스에 인스턴스가 하나만 있도록 하면서 이 인스턴스에 대한 전역 접근(엑세스) 지점을 제공하는 생성 디자인 패턴입니다. 이렇게 정의로만 설명하면 말이 어려워 보일 수 있지만 실제 사용 사례들을 들어보면 그렇게 어려운 개념이 아니라는 것을 알 수 있습니다.Car라는 클래스를 이용하여 서로에게 영향을 미치지 않은 독립적인 상태를 갖는 여러 객체를 생성하였습니다. 하지만 만약 우리가 객체가 서로 독립적인 상태 가 아닌 공유 리소스를 갖는 여러 객체를 생성한다고 할 경우는 어떻게 해야 할까요? 또 다른 예시로 자세히 설명해보겠습니다.country의 값은 뭐가 나올까요? 정답은 undefined 입니다! 왜냐하면 db2 에서는 DB에 대한 인스턴스가 새로 생성되었기 때문에 서로 공유된 자원이 아닌 독립된 상태를 지니기 때문에 db1에서 설정한 sunub에 대한 값은 공유가 되는 것이 아니기 때문에 db1 에서만 사용이 가능합니다.싱글턴 패턴입니다!!static 을 이용하여 new 연산자를 이용하여 새로운 인스턴스를 생성하지 않고 인스턴스의 수를 하나로 제한하여 공용 리소스를 사용할 수 있습니다. 하지만 위의 방법에는 진정한 싱글턴이 아니라는 문제가 존재합니다. 이 문제는 constructor 값이 private 값으로 설정되어 있지 않기 때문에 강제로 싱글턴 패턴을 이용하게끔 만들 수는 없다는 문제가 있습니다. 여기서 우리는 typescript의 위대함을 또 다시 느낄 수 있습니다. javascript에서는 이 문제를 해결하기 위해 다음과 같은 과정을 거쳐야 합니다.typescript가 등장한다면 어떻게 될까요?class Car {
constructor(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
this.speed = 0;
}
accelerate(amount) {
this.speed += amount;
}
brake(amount) {
this.speed = Math.max(0, this.speed - amount);
}
}
const car1 = new Car("KIA", "K7", 2022);
const car2 = new Car("HYNDAI", "Sonata", 2023);
function singleton<Value>(name: string, value: () => Value): Value {
const yolo = global as any;
yolo.__singleton ??= {};
yolo.__singleton[name] ??= value();
return yolo.__singleton[name];
}
declare global {
interface Global {
__singleton?: Map<string, unknown>;
}
}
interface Global {
__singleton?: Map<string, unknown>;
}
export function singleton<Value>(name: string, value: () => Value): Value {
const thusly = globalThis as Global;
thusly.__singleton ??= new Map();
if (!thusly.__singleton.has(name)) {
thusly.__singleton.set(name, value());
}
return thusly.__singleton.get(name) as Value;
}
class DB {
constructor() {
this.table = {};
}
set(name, value) {
this.table[name] = value;
}
get(name) {
return this.table[name];
}
}
const db1 = new DB();
db1.set("sunub", { country: "Korea" });
const db2 = new DB();
const { country } = db2.get("sunub");
class Singleton {
static #instance = null;
constructor() {}
getInstance() {
if (Singleton.#instance == null) {
Singleton.#instance = new Singleton();
}
return Singleton.#instance;
}
}
const Singleton = (() => {
const constructorKey = Symbol("constructor");
return class {
static #instance = null;
constructor(key) {
if (key !== constructorKey) {
throw new Error("Private constructor, use getInstance() method.");
}
}
static getInstance() {
if (!Singleton.#instance) {
Singleton.#instance = new Singleton(constructorKey);
}
return Singleton.#instance;
}
};
})();
class Singleton {
private static instance: Singleton | null = null;
private constructor() {}
public static getInstance(): Singleton {
if (Singleton.instance === null) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
}