是否有可能将全局范围注入ES6中的实例化类,即单例?

时间:2017-05-23 08:15:53

标签: javascript node.js ecmascript-6

首先,我需要道歉,因为这将有很多代码,这将使这个问题膨胀。不过,我认为这有助于更好地理解我的问题。

让我说我给了MainModule

'use strict';

/**
 * Loads Module from given name.
 * @class {LoadModules}
 */
class LoadModules {

  constructor(moduleName) {
    // define Modulename.
    this.moduleName = moduleName;
  }

  /**
   * Initialize module.
   * @method init
   * @return {void} [nothing]
   */
  init() {

    // Path Module.
    const path = require('path');

    // Require Module from given Name.
    let ModuleToLoad = require(path.join(__dirname, 'Modules', this.moduleName, this.moduleName + '.js'));
    // Instatiate Module.
    ModuleToLoad = new ModuleToLoad();
    // Start module.
    ModuleToLoad.init();
  }

}

另一个可以加载到MainModule

的模块
/**
 * This is a Module which can be loaded by the MainModule.
 * @class {ModuleToBeLoaded}
 */
module.exports = class ModuleToBeLoaded {

  constructor() {
    /**
     * Empty
     */
  }

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    console.log('module Loaded');
  }

};

正如您所看到的,它用于动态加载模块,这非常合适。

我的问题是我动态加载其他模块的MainModule无法在模块之间共享自己的全局范围,或者至少我没弄清楚如何。我很清楚这很复杂,因为MainModuleModuleToBeLoaded位于不同的文件中。

例如,我LoggerClass的全球范围内有MainModule

// This is in the global scope.
const LoggerClass = new Logger();
/**
* LoadModule class stuff comes after this.
*/

我希望所有模块都可以访问LoggerClass,就像它们在自己的全局范围内一样,而不是在每个模块中一次又一次地定义它。作为示例,我会将console.log类中的ModuleToBeLoaded更改为:

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    LoggerClass.log('module Loaded');
  }

所以基本上我在MainModule中定义了Globals,我想在ModuleToBeLoaded的代码中访问这些Globals。可能的解决方案是更改constructor中的ModuleToBeLaoded。像这样:

  constructor(LoggerClass) {
    // Here I can set LoggerClass internally.
    this.LoggerClass = LoggerClass;
  }

  /**
   * Initialize newly loaded Module.
   * @method init
   * @return {void} [nothing]
   */
  init() {
    this.LoggerClass.log('module Loaded');
  }

这可以让我像这样实例化这个类:

// Instatiate Module.
ModuleToLoad = new ModuleToLoad(LoggerClass);

这是正确的方法,还是更优选其他解决方案?

我想要实现的是ES6中的已知模式singelton pattern。 有关更多信息,请查看此Wikipage:https://en.wikipedia.org/wiki/Singleton_pattern

旁注:我在NodeJS 7.10.0环境中没有任何第三方库。

此致 Megajin

2 个答案:

答案 0 :(得分:2)

LoggerClass.js 这就是你制作单身人士的方式(总是同一个实例)

let instance;
module.exports = function () {
  if (!instance) {
    instance = new LoggerClass();
  }
  return instance;
}

class LoggerClass {
  constructor() {
    this.instanceData = Date.now();
  }
  log() {
    console.log(`logging secret instance: ${this.instanceData}`);
  }
}

<强> LoadModules.js

const getLoggerClass = require('./LoggerClass');

module.exports = class LoadModules {
  constructor(moduleName) {
    this.moduleName = moduleName;
  }

  init() {
    const path = require('path');
    // changed the require statement, to make it simpler
    let ModuleToLoad = require(path.join(__dirname, this.moduleName + '.js'));
    ModuleToLoad = new ModuleToLoad(getLoggerClass());
    ModuleToLoad.init();
  }
}

<强> ModuleToLoad.js

module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded module Loaded');
    this.logger.log();
  }
};

<强> ModuleToLoad2.js

module.exports = class ModuleToBeLoaded {
  constructor(logger) {
    this.logger = logger;
  }
  init() {
    console.log('ModuleToBeLoaded2 module Loaded');
    this.logger.log();
  }
};

<强>演示

> node
> const LoadModules = require('./LoadModules');
> var load = new LoadModules('ModuleToLoad');
> var load2 = new LoadModules('ModuleToLoad2');

> load.init();
ModuleToBeLoaded module Loaded
logging secret instance: 1495528699144
> load2.init();
ModuleToBeLoaded2 module Loaded
logging secret instance: 1495528699144

正如您所注意到的,根据 LoggerClass

this.instanceData,实例是相同的

删除评论以使代码更少

答案 1 :(得分:0)

我觉得很奇怪,你有一个单独的constructorinit。为什么不在构造函数中进行初始化?

无论如何,似乎正确的方法确实是通过你的全球&#34;到要加载的模块的构造函数或初始化。

如果您真的希望它是全局的,可以将其添加到global命名空间。