2016-10-15 10 views
4
class Foo{ 

} 

var instance: Foo; 
export function getFooInstance(){ 
    /* logic */ 
} 

またはTypescript/ES6のシングルトンパターンにはどのような方法が適していますか?

export class Foo{ 
    private static _instance; 
    private constructor(){}; 
    public getInstance(){/* logic */} 
} 

// Use it like this 
Foo.getInstance() 

私は、オブジェクトの一方向のみのインスタンスがあることを確認したいですか?これ以外の提案はありますか?両方のための

活字体遊び場link

+3

サイドノート:JavaScriptでは、実際にインスタンスに対して制限が適用されることはありません。継承はクラス間ではなくオブジェクト間(プロトタイプ)であるため、 'var second = Object.create(Object.getPrototypeOf(singleton));'という2番目のインスタンスを作成することは常に可能です。はい、これは 'new Foo()'よりも面倒です。 –

答えて

5

あなたがクラスにゲッターを使用する場合、それは静的である必要があります:

export class Foo{ 
    private static _instance; 
    private constructor(){}; 
    public static getInstance(){/* logic */} 
} 

事は、コンパイラは、このプライベート可視性を強化する一方ということです実行時に、たとえ誰かがjavascriptのものを直接使用したとしても、意図せずにバイパスすることは可能です。

あなたはモジュール/名前空間を使用して、それを強制するならば、あなたはそれを完全に隠すことができます。

モジュールを使用する:

export interface IFoo {} 

class Foo implements IFoo {} 

var instance: Foo; 
export function getFooInstance(): IFoo { 
    /* logic */ 

    return instance; 
} 

それはあなたのコードですが、私はまた、エクスポートされIFooインタフェースを(aded )ので、誰がインスタンスを取得するかは、インターフェイスではなく、クラスを知ることになります。名前空間の使用

:JSので、活字体で

namespace Foo { 
    export interface IFoo {} 

    class FooClass implements IFoo {} 

    const instance = new FooClass(); 
    export function getInstance(): IFoo { 
     return instance; 
    } 
} 
+0

ありがとうございます。これは私が探していたものです。 –

4

は、あなたが本当に一つだけのインスタンスをしたい場合は、理由だけで、オブジェクトリテラルをエクスポートすることで、言語自体のw /強制ではありませんか?

const Foo = { 
    doSomething() { 

    } 
} 

export default Foo; 

IMO、これはKISSに従ったもので、定型文の量は少なく、誰でも複数のインスタンスを作成する方法はありません。

あなたは関数を直接エクスポートすることもできます。モジュール自体があなたのためにシングルトンとして機能できることを忘れないでください。

export function doSomething() { 
} 

インポートしてオブジェクトとして扱いたい場合は、インポート*を使用できます。関数が実際にオブジェクトに属し、すべてのステートレスな静的関数ではない場合、私は最初のアプローチを好む。

import * as Foo from './Foo'; 

Foo.doSomething(); 
2

シングルトンクラスの新しいインスタンスを作成するかどうかによって異なります。最後のケースではgetInstanceを省略することができ、クラスのコンストラクタは、シングルトンの工場として機能してもよい:

class Foo { 
    private static _instance; 
    constructor(...args) { 
     if (Foo._instance) { 
      return Foo._instance; 
     } 

     // if Foo extends non-singleton class or whatever, 
     // super(...args); 

     Foo._instance = this; 
    }; 
} 

同じことを同じように、任意のクラスのデコレータを行うことができますために

@singleton 
class Foo { ... } 

function singleton(Class) { 
    function extend(sub, sup) { 

     for (var prop in sup) 
      if (sup.hasOwnProperty(prop)) 
       sub[prop] = sup[prop]; 

     function __() { 
      this.constructor = sub; 
     } 

     __.prototype = sup.prototype; 
     sub.prototype = new __(); 
    }; 

    const Singleton = <any>function (...args) { 
     if (Singleton._instance) { 
      return Singleton._instance; 
     } 

     Class.apply(this, args); 

     Singleton._instance = this; 
    } 

    extend(Singleton, Class); 

    return Singleton; 
} 
:いくつかの typing problems with TypeScript decorators、カスタム継承コードが存在するという事実は singletonデコレータの代わり Singleton extends Class内部で使用する必要があります3210

入力を傷つけることがありますが、構文はきちんとしています。

関連する問題