如何在TypeScript中定义Singleton

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在TypeScript中定义Singleton相关的知识,希望对你有一定的参考价值。

在TypeScript中为类实现Singleton模式的最佳和最方便的方法是什么? (有和没有延迟初始化)。

答案

TypeScript中的Singleton类通常是反模式。您可以简单地使用命名空间。

Useless singleton pattern

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

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

Namespace equivalent

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
另一答案

我的解决方案:

export default class Modal {
    private static _instance : Modal = new Modal();

    constructor () {
        if (Modal._instance) 
            throw new Error("Use Modal.instance");
        Modal._instance = this;
    }

    static get instance () {
        return Modal._instance;
    }
}
另一答案

在Typescript中,不一定要遵循new instance() Singleton方法。导入的无构造函数的静态类也可以同样工作。

考虑:

export class YourSingleton {

   public static foo:bar;

   public static initialise(_initVars:any):void {
     YourSingleton.foo = _initvars.foo;
   }

   public static doThing():bar {
     return YourSingleton.foo
   }
}

您可以导入该类并在任何其他类中引用YourSingleton.doThing()。但请记住,因为这是一个静态类,它没有构造函数所以我通常使用从导入Singleton的类调用的intialise()方法:

import {YourSingleton} from 'singleton.ts';

YourSingleton.initialise(params);
let _result:bar = YourSingleton.doThing();

不要忘记在静态类中,每个方法和变量也需要是静态的,所以不使用this而是使用完整的类名YourSingleton

另一答案

我想也许使用泛型是面糊

class Singleton<T>{
    public static Instance<T>(c: {new(): T; }) : T{
        if (this._instance == null){
            this._instance = new c();
        }
        return this._instance;
    }

    private static _instance = null;
}

如何使用

步骤1

class MapManager extends Singleton<MapManager>{
     //do something
     public init():void{ //do }
}

第2步

    MapManager.Instance(MapManager).init();
另一答案

这是使用IFFE更常规的javascript方法来实现它的另一种方法:

module App.Counter {
    export var Instance = (() => {
        var i = 0;
        return {
            increment: (): void => {
                i++;
            },
            getCount: (): number => {
                return i;
            }
        }
    })();
}

module App {
    export function countStuff() {
        App.Counter.Instance.increment();
        App.Counter.Instance.increment();
        alert(App.Counter.Instance.getCount());
    }
}

App.countStuff();

查看demo

另一答案

另一种选择是在模块中使用符号。这样,您可以保护您的课程,如果您的API的最终用户使用正常的Javascript:

let _instance = Symbol();
export default class Singleton {

    constructor(singletonToken) {
        if (singletonToken !== _instance) {
            throw new Error("Cannot instantiate directly.");
        }
        //Init your class
    }

    static get instance() {
        return this[_instance] || (this[_instance] = new Singleton(_singleton))
    }

    public myMethod():string {
        return "foo";
    }
}

用法:

var str:string = Singleton.instance.myFoo();

如果用户正在使用您编译的API js文件,如果他尝试手动实例化您的类,也会收到错误:

// PLAIN JAVASCRIPT: 
var instance = new Singleton(); //Error the argument singletonToken !== _instance symbol
另一答案
class MySingleton {
constructor(message) {
    alert('hello' + message);
}
private static instance: MySingleton;
private static instance2: MySingleton;

public static getSessionStorageInstance() {
    if (!MySingleton.instance) {
        MySingleton.instance = new MySingleton("world");
    }
    return MySingleton.instance;
}

public static getSessionStorageInstance2() {
    if (!MySingleton.instance2) {
        MySingleton.instance2 = new MySingleton("youu");
    }
    return MySingleton.instance2;
 }
}

 const a: MySingleton = MySingleton.getSessionStorageInstance();
 const b: MySingleton = MySingleton.getSessionStorageInstance2();

 alert(a === b)
另一答案

不是纯粹的单身人士(初始化可能不是懒惰的),而是在namespaces的帮助下的类似模式。

namespace MyClass
{
    class _MyClass
    {
    ...
    }
    export const instance: _MyClass = new _MyClass();
}

访问Singleton的对象:

MyClass.instance
另一答案

这是最简单的方法

class YourSingletoneClass {
  private static instance: YourSingletoneClass;

  private constructor(public ifYouHaveAnyParams: string) {

  }
  static getInstance() {
    if(!YourSingletoneClass.instance) {
      YourSingletoneClass.instance = new YourSingletoneClass('If you have any params');
    }
    return YourSingletoneClass.instance;
  }
}
另一答案
namespace MySingleton {
  interface IMySingleton {
      doSomething(): void;
  }
  class MySingleton implements IMySingleton {
      private usePrivate() { }
      doSomething() {
          this.usePrivate();
      }
  }
  export var Instance: IMySingleton = new MySingleton();
}

通过这种方式,我们可以应用界面,这与Ryan Cavanaugh接受的答案不同。

另一答案

从TS 2.0开始,我们就能够定义visibility modifiers on constructors,所以现在我们可以像在其他语言中习惯的那样在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;

感谢@Drenai指出如果使用原始编译的javascript编写代码,则无法防止多个实例化,因为TS的约束消失并且构造函数不会被隐藏。

另一答案

我发现的最好方法是:

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() );

http://www.codebelt.com/typescript/typescript-singleton-pattern/

另一答案

以下方法创建一个Singleton类,可以像传统类一样使用:

class Sin

以上是关于如何在TypeScript中定义Singleton的主要内容,如果未能解决你的问题,请参考以下文章

单例模式(singleton)

单例模式(singleton)

如何在 TypeScript 中迭代自定义文字类型?

如何在 TypeScript 接口中定义静态属性

如何在 TypeScript 定义文件中使用外部模块的类型?

如何使用 TypeScript 在接口中定义对象的命名数组?