ES6:将基类限制为单例

时间:2017-05-27 21:39:38

标签: javascript ecmascript-6 javascript-objects es6-class

我有一个超级类(基类)的两(2)个子类;如果我有新的B和C,我会得到两个实例 - 两者都包含扩展的基类。

  

问题:是否可以对super进行Singleton限制   上课,如果有,怎么样?

class A {
  constructor(id) {
    // => I don't want to make this call (2) times, 
    //  once for B and again for C.
    let {
      firstName: this._FirstName 
    } = CollectionName.findOne({userId: id}); 
  }
}

export class B extends A {
  constructor(id) {
    super(id);
  }
  get FirstName() {
    return this._FirstName;
  }
}

export class C extends A {
  constructor(id) {
    super(id);
  }
  get FirstName() {
    return this._FirstName;
  }
}



import { B, C } from 'imports/server/a-b-c.js'

const b = new B('123')

const c = new B('456')

const FirstNameB = b.FirstName;

const FirstNameC = c.FirstName;

编辑:

我将尝试回答这些问题。

  

@ Quasimodo克隆:你有什么打算使用单身人士模式?如果子类化可以生成多个超类实例,您是否有疑问?或者您是否尝试阻止多个子类实例 - 超类应该强制新C一直返回相同的C实例?

基类调用MongoDB并检索大量数据(如果只有一个类是基类)。当我有两个类扩展基类时,我不想呼叫Mongo并多次存储所有数据。 ATM我使用单例模式来防止这种情况发生在单独的类中,但在我有两个使用相同基类的类的情况下,我真的很喜欢使用这种模式。

以不同的方式说, 我已经验证的问题正在发生:当我有两个类调用一个基类时,基类的构造函数被调用两次,而Mongo被调用两次。 ATM当我通过扩展调用时,我没有为基类设置单例模式。

现在我需要弄清楚如何在由多个类扩展的基类上应用单例模式。由于基类实际上是子类的同一个实例,我甚至不知道这是否可行。

1 个答案:

答案 0 :(得分:1)

让我们首先向控制台生成一些测试输出。您应该在浏览器中运行它以获得功能齐全的控制台访问权限:



class Base
{
    constructor(value)
    {
        this.prop = value;
    }

    funcBase() {}
}

class B extends Base
{
    constructor(value)
    {
        super(value);
    }

    funcB() {}
}

class C extends Base
{
    constructor(value)
    {
        super(value);
    }

    funcC() {}
}

let
    b = new B('instance b'),
    b2= new B('instance b'),
    c = new C('instance c')
;

// Do instances of class B and class C have the identical prototype?
console.log( 'proto(b) === proto(c)',
              Object.getPrototypeOf(b) === Object.getPrototypeOf(c)  );
              // false

// Do the prototypes of those instances b and c have the idendical prototype?
console.log( 'proto-proto(b) === proto-proto(c)',
              Object.getPrototypeOf(Object.getPrototypeOf(b)) === Object.getPrototypeOf(Object.getPrototypeOf(c)) );
              //true

// Do two instances of class B have the identical prototype?
console.log( 'proto(b) === proto(b2)',
              Object.getPrototypeOf(b) === Object.getPrototypeOf(b2) );
              // true

// Is b's prototype's prototype identical to Base.prototype?
console.log( 'proto-proto(b) === Base.prototype',
  Object.getPrototypeOf(Object.getPrototypeOf(b)) === Base.prototype );
//true

// Let's inspect the prototypes in the console
// What is the prototype of b
console.log( Object.getPrototypeOf(b) );                        // an instance with constructor B() and funcB()

// What is the b's prototype's prototye?
console.log( Object.getPrototypeOf(Object.getPrototypeOf(b)) ); // an instance with constructor Base() and funcBase()

// Inspect constructor function B()
try      { console.dir( B ); }
catch(e) { console.log( B ); }  // [right click the "B" in the output and open in variable inspector]




如您所见,class关键字实际上为您编译了构造函数和原型实例。 该实例由其prototype属性中的构造函数引用。如果它扩展了一个超类,那么原型的原型将与超类构造函数的prototype属性相同(参见下面的__proto__属性)。当你创建 使用关键字new创建B类的新实例,创建一个新对象并引用原型 由构造函数分配给新对象的原型。大多数浏览器在__proto__属性中公开实例的原型。但是,您应该通过Object.getPrototype方法访问它。

在检查器中,您可以使用__proto__属性遍历树。

因此,您的问题的答案是:您不需要单一设计模式,因为相同的原型 一旦在构造函数创建时实例化,每次使用关键字new创建新的时,都会重复使用 实例。比较Object.getPrototypeOf(Object.getPrototypeOf(b)) === Object.getPrototypeOf(Object.getPrototypeOf(c)) )时,您可以在示例中看到行为。两个原型链都引用相同的超类实例。

您应该阅读有关JavaScript原型概念的更多文档。它可能看起来非常复杂和奇怪,特别是当你来自典型的OOP语言时,它基于一个非常简单的设计。