javascript Typescript/ES6中的Singleton模式的正确方法是什么?

krcsximq  于 2024-01-05  发布在  Java
关注(0)|答案(3)|浏览(226)
  1. class Foo{
  2. }
  3. var instance: Foo;
  4. export function getFooInstance(){
  5. /* logic */
  6. }

字符串

  1. export class Foo{
  2. private static _instance;
  3. private constructor(){};
  4. public getInstance(){/* logic */}
  5. }
  6. // Use it like this
  7. Foo.getInstance()


我想确保对象的示例只有一个方式?除了这个,还有其他建议吗?
Typescript Playground链接:

zvokhttg

zvokhttg1#

如果你想在类中使用getter,那么它需要是静态的:

  1. export class Foo{
  2. private static _instance;
  3. private constructor(){};
  4. public static getInstance(){/* logic */}
  5. }

字符串
问题是,虽然编译器会强制执行这种私有可见性,但在运行时,它仍然有可能绕过它,即使是无意的,例如有人直接从JavaScript使用它。
如果你使用模块/命名空间来强制它,那么你可以完全隐藏它:
使用模块:

  1. export interface IFoo {}
  2. class Foo implements IFoo {}
  3. var instance: Foo;
  4. export function getFooInstance(): IFoo {
  5. /* logic */
  6. return instance;
  7. }


这是你的代码,我只是添加了IFoo接口(也是导出的),这样无论谁得到一个示例都会知道接口,但不知道类。
使用命名空间:

  1. namespace Foo {
  2. export interface IFoo {}
  3. class FooClass implements IFoo {}
  4. const instance = new FooClass();
  5. export function getInstance(): IFoo {
  6. return instance;
  7. }
  8. }

展开查看全部
wydwbb8l

wydwbb8l2#

在JS和TypeScript中,如果你真的只想要一个示例,为什么不通过导出一个对象字面量来强制使用语言本身呢?

  1. const Foo = {
  2. doSomething() {
  3. }
  4. }
  5. export default Foo;

字符串
IMO,这是遵循KISS,最少的样板,任何人都没有办法创建多个示例。
也就是说,你也可以直接导出函数。记住,模块本身可以作为单例。

  1. export function doSomething() {
  2. }


然后导入并想把它当作一个对象,你可以使用import *。如果函数真的属于对象,而不是所有的无状态静态函数,我更喜欢第一种方法。

  1. import * as Foo from './Foo';
  2. Foo.doSomething();

展开查看全部
huwehgph

huwehgph3#

这取决于是否应该有机会为单例类创建一个新的示例。在最后一种情况下,getInstance可以省略,类构造函数可以充当单例工厂:

  1. class Foo {
  2. private static _instance;
  3. constructor(...args) {
  4. if (Foo._instance) {
  5. return Foo._instance;
  6. }
  7. // if Foo extends non-singleton class or whatever,
  8. // super(...args);
  9. Foo._instance = this;
  10. };
  11. }

字符串
同样的事情可以用装饰器为任意类做,比如:

  1. @singleton
  2. class Foo { ... }


由于存在一些typing problems with TypeScript decorators,因此应该在singleton装饰器中使用自定义继承代码,而不是Singleton extends Class

  1. function singleton(Class) {
  2. function extend(sub, sup) {
  3. for (var prop in sup)
  4. if (sup.hasOwnProperty(prop))
  5. sub[prop] = sup[prop];
  6. function __() {
  7. this.constructor = sub;
  8. }
  9. __.prototype = sup.prototype;
  10. sub.prototype = new __();
  11. };
  12. const Singleton = <any>function (...args) {
  13. if (Singleton._instance) {
  14. return Singleton._instance;
  15. }
  16. Class.apply(this, args);
  17. Singleton._instance = this;
  18. }
  19. extend(Singleton, Class);
  20. return Singleton;
  21. }


它可能会影响打字,但语法保持整洁。

展开查看全部

相关问题