[singleton] TypeScript에서 싱글 톤을 정의하는 방법

TypeScript에서 클래스에 대한 싱글 톤 패턴을 구현하는 가장 쉽고 편리한 방법은 무엇입니까? (게으른 초기화 유무에 관계없이).



답변

TypeScript의 싱글 톤 클래스는 일반적으로 안티 패턴입니다. 네임 스페이스를 간단하게 사용할 수 있습니다대신 를 .

쓸모없는 싱글 톤 패턴

class Singleton {
    /* ... lots of singleton logic ... */
    public someMethod() { ... }
}

// Using
var x = Singleton.getInstance();
x.someMethod();

네임 스페이스 동등

export namespace Singleton {
    export function someMethod() { ... }
}
// Usage
import { SingletonInstance } from "path/to/Singleton";

SingletonInstance.someMethod();
var x = SingletonInstance; // If you need to alias it for some reason


답변

TS 2.0부터 생성자에 가시성 수정자를 정의 할 수 있습니다. 할 수 있으므로 이제 다른 언어에서 사용하는 것처럼 TypeScript에서 싱글 톤을 수행 할 수 있습니다.

주어진 예 :

class MyClass
{
    private static _instance: MyClass;

    private constructor()
    {
        //...
    }

    public static get Instance()
    {
        // Do you need arguments? Make it a regular static method instead.
        return this._instance || (this._instance = new this());
    }
}

const myClassInstance = MyClass.Instance;

원시 컴파일 된 자바 스크립트를 사용하여 코드를 작성하면 TS의 제약 조건이 사라지고 생성자가 숨겨지지 않기 때문에 다중 인스턴스화에 대한 보호 기능이 없다는 점에 대해 @Drenai에게 감사드립니다.


답변

내가 찾은 가장 좋은 방법은 다음과 같습니다.

class SingletonClass {

    private static _instance:SingletonClass = new SingletonClass();

    private _score:number = 0;

    constructor() {
        if(SingletonClass._instance){
            throw new Error("Error: Instantiation failed: Use SingletonClass.getInstance() instead of new.");
        }
        SingletonClass._instance = this;
    }

    public static getInstance():SingletonClass
    {
        return SingletonClass._instance;
    }

    public setScore(value:number):void
    {
        this._score = value;
    }

    public getScore():number
    {
        return this._score;
    }

    public addPoints(value:number):void
    {
        this._score += value;
    }

    public removePoints(value:number):void
    {
        this._score -= value;
    }

}

사용 방법은 다음과 같습니다.

var scoreManager = SingletonClass.getInstance();
scoreManager.setScore(10);
scoreManager.addPoints(1);
scoreManager.removePoints(2);
console.log( scoreManager.getScore() );

https://codebelt.github.io/blog/typescript/typescript-singleton-pattern/


답변

다음 접근 방식은 기존 클래스처럼 정확하게 사용할 수있는 Singleton 클래스를 만듭니다.

class Singleton {
    private static instance: Singleton;
    //Assign "new Singleton()" here to avoid lazy initialisation

    constructor() {
        if (Singleton.instance) {
            return Singleton.instance;
        }

        this. member = 0;
        Singleton.instance = this;
    }

    member: number;
}

마다 new Singleton() 작업은 동일한 인스턴스를 반환합니다. 그러나 이것은 사용자가 예상하지 못한 것일 수 있습니다.

다음 예제는 사용자에게 더 투명하지만 다른 사용법이 필요합니다.

class Singleton {
    private static instance: Singleton;
    //Assign "new Singleton()" here to avoid lazy initialisation

    constructor() {
        if (Singleton.instance) {
            throw new Error("Error - use Singleton.getInstance()");
        }
        this.member = 0;
    }

    static getInstance(): Singleton {
        Singleton.instance = Singleton.instance || new Singleton();
        return Singleton.instance;
    }

    member: number;
}

용법: var obj = Singleton.getInstance();


답변

실제로 다음과 같은 패턴이 보이지 않는 것에 놀랐습니다. 실제로 매우 단순 해 보입니다.

// shout.ts
class ShoutSingleton {
  helloWorld() { return 'hi'; }
}

export let Shout = new ShoutSingleton();

용법

import { Shout } from './shout';
Shout.helloWorld();


답변

이것을 위해 클래스 표현식을 사용할 수 있습니다 (1.6 생각대로).

var x = new (class {
    /* ... lots of singleton logic ... */
    public someMethod() { ... }
})();

또는 클래스가 내부적으로 유형에 액세스 해야하는 경우 이름

var x = new (class Singleton {
    /* ... lots of singleton logic ... */
    public someMethod(): Singleton { ... }
})();

또 다른 옵션은 정적 멤버를 사용하여 싱글 톤 내부에서 로컬 클래스를 사용하는 것입니다

class Singleton {

    private static _instance;
    public static get instance() {

        class InternalSingleton {
            someMethod() { }

            //more singleton logic
        }

        if(!Singleton._instance) {
            Singleton._instance = new InternalSingleton();
        }

        return <InternalSingleton>Singleton._instance;
    }
}

var x = Singleton.instance;
x.someMethod();


답변

모든 클래스에 다음 6 줄을 추가하여 “Singleton”으로 만듭니다.

class MySingleton
{
    private constructor(){ /* ... */}
    private static _instance: MySingleton;
    public static getInstance(): MySingleton
    {
        return this._instance || (this._instance = new this());
    };
}

테스트 예 :

var test = MySingleton.getInstance(); // will create the first instance
var test2 = MySingleton.getInstance(); // will return the first instance
alert(test === test2); // true

[편집] : 메서드 대신 속성을 통해 인스턴스를 가져 오려면 Alex 응답을 사용하십시오.