如何在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)
不是纯粹的单身人士(初始化可能不是懒惰的),而是在namespace
s的帮助下的类似模式。
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的主要内容,如果未能解决你的问题,请参考以下文章