专业的Singleton实现

时间:2017-01-16 15:29:55

标签: oop design-patterns typescript

我正在寻找专门的单例实现,可能我可能使用了错误的术语,因此寻找专家建议。这是我的情景:

可以通过ComponentA或ComponentB调用公共代码。我需要从公共代码推送遥测数据。遥测需要有关于ComponentA或ComponentB是否调用此公共代码的信息。

所以常见的代码只有这行代码:

telemetry.pushData(this._area,data);

其中this._area告诉遥测数据被推送到哪个组件

我需要从多个地方推送遥测数据,这样如果对象被创建一次并在代码生存期内使用它将会很好

我可以考虑将组件上下文传递给公共代码的一个选项,考虑到这种情况看起来不正确,因此寻找建议在这种情况下应该使用哪种模式?

这就是我的想法

// Telemetry.ts file present in shared code

export class Telemetry extends Singleton {
public constructor() {
    super();
}

public static instance(): Telemetry {
    return super.instance<Telemetry>(Telemetry);
}

public publishEvent(data): void {
    if (!this.area) {
        throw new Error("Error: Initialize telemetry class with right area");
    }

    pushtelemetryData(this.area, data);
}

public area: string;
}



// Create Telemetry object from component A
Telemetry.instance().area = "ComponentA";

// Shared code will call telemetry publishEvent
Telemetry.instance().publishEvent(data);

由于

2 个答案:

答案 0 :(得分:0)

在TypeScript中使用它不是一个很好的模式,你通常会注入依赖项。

如果你必须绝对这样做,你可以通过伪造它来做到这一点:

namespace Telemetry {
    var instance : SingletonSomething;

    export function push(data: Any) : void {
        if (instance == null) {
            instance = new SingletonSomething();
        }
        instance.push(data);
    }

    class SingletonSomething() { ... }
}

然后你可以打电话

Telemetry.push(data);

答案 1 :(得分:0)

您可以轻松地模仿打字稿中的单身人士模式:

class Telemetry {
    private static instance: Telemetry;

    public static getInstance(): Telemetry {
        if (Telemetry.instance == null) {
            Telemetry.instance = new Telemetry();
        }

        return Telemetry.instance;
    }
    ...
}

如果你的代码有某种闭包(模块,命名空间等),那么你可以用以下代码替换静态成员:

let telemetryInstance: Telemetry;
export class Telemetry {
    public static getInstance(): Telemetry {
        if (telemetryInstance == null) {
            telemetryInstance = new Telemetry();
        }

        return telemetryInstance;
    }
    ...
}

但是你也可以用以下方法替换静态方法:

let telemetryInstance: Telemetry;
export function getTelemetryInstance(): Telemetry {
    if (telemetryInstance == null) {
        telemetryInstance = new Telemetry();
    }

    return telemetryInstance;
}

export class Telemetry {
    ...
}

此时,如果你正在使用某种关闭,你可能会问自己是否真的需要这个课程?
如果您将其用作模块:

// telemetry.ts
export interface TelemetryData {
    ...
}

export function pushData(data: TelemetryData): void {
    ...
} 

然后你就会得到你正在寻找的东西,而这更像是&#34; javascript方式&#34;这样做。

修改

在遥测模块中,无需了解其用户 如果Telemetry.pushData函数需要有关于调用它的对象的信息,那么为它定义一个接口:

// telemetry.ts
export interface TelemetryData {
    ...
}

export interface TelemetryComponent {
    name: string;
    ...
}

export function pushData(data: TelemetryData, component: TelemetryComponent): void {
    ...
}

然后在其他模块中,您使用它:

// someModule.ts
import * as Telemetry from "./telemetry";

class MyComponent implement Telemetry.TelemetryComponent {
    // can also be a simple string property
    public get name() {
        return "MyComponent";
    }

    fn() {
        ...
        Telemetry.pushData({ ... }, this);
    }
}

第二次编辑

因为您使用的是模块系统,所以您的模块文件足以制作单身人士,因此不需要课程来实现这一目标。
你可以这样做:

// telemetry.ts
let area: string;

export interface TelemetryData {
    ...
}

export function setArea(usedArea: string) {
    area = usedArea;
}

export function pushData(data: TelemetryData): void {
    ...
}

然后:

Telemetry.setArea("ComponentA");
...
Telemetry.publishEvent(data);

遥测模块每页仅创建一次,因此您可以将整个模块视为单个模块 仅导出所需的功能。