Switching between singleton and prototype scope using RequireJS

自古美人都是妖i 提交于 2019-12-08 07:51:27

问题


Spring has very useful option, that whey I define a bean, I define a scope. If it's singleton, only one instance is created. By prototype, each time a bean is required, a new instance is created.

RequireJS provides by default singletons, so with such simple module:

Singleton.js

define([], function() {
    console.log('Instance  initialization')
    var items = []
    var singleton =  {
      getItems: function() {
        return items
      },
      setItems: function(newItems) {
        items = newItems
      },
      addItem: function(item) {
        items.push(item)
      }
    };
    return singleton;
})

and the usage:

require(["showcase/modules/Singleton"], function(Singleton){
  Singleton.addItem('item1')
  console.log(Singleton.getItems())
})
require(["showcase/modules/Singleton"], function(Singleton){
  Singleton.addItem('item2')
  console.log(Singleton.getItems())
})

the output will be:

Instance initialization ["item1"] ["item1", "item2"]

Is it possible to define and use the module in such way, that I could switch in the module definition, if I want to use prototype or singleton scope? So in my case, without changing the usage, I'd get:

Instance initialization ["item1"] Instance initialization ["item2"]

I'm using RequireJS from Dojo, just in case of syntax differences


回答1:


Well, first of all the problem is that when you import a module using an AMD loader, you will actually get an instance, but the second time you import the same module, the same instance is actually returned (problem 1).

To overcome this problem you should use the factory design pattern to get your instance and also translate your singleton object to a class that can be instantiated (problem 2). Your factory could have a method called getInstance() that accepts a boolean parameter that can toggle between singleton/prototype.

So without changing your usage you won't be able to do this because of the problems I just addressed. The best solution I can come up with (with a factory) is:

Singleton.js

define([], function() {
    console.log('Instance  initialization');

    // Singleton class
    var Singleton = function() {
      this.items = [];
      this.getItems = function() {
        return this.items;
      };
      this.setItems = function(newItems) {
        this.items = newItems;
      };
      this.addItem = function(item) {
        this.items.push(item);
      }
    };

    // Factory
    var factory = {
      singletonInstance: new Singleton(),
      getInstance: function(/** Boolean */ isSingleton) {
        if (isSingleton === true) {
          return this.singletonInstance;
        } else {
          return new Singleton();
        }
      }
    };
    return factory;
});

Usage (singleton)

require(["app/Singleton"], function(singletonFactory){
  var Singleton = singletonFactory.getInstance(true);
  Singleton.addItem('item1');
  console.log(Singleton.getItems());
});
require(["app/Singleton"], function(singletonFactory){
  var Singleton = singletonFactory.getInstance(true);
  Singleton.addItem('item2');
  console.log(Singleton.getItems());
});

Usage (multiple instances)

require(["app/Singleton"], function(singletonFactory){
  var Singleton = singletonFactory.getInstance(false);
  Singleton.addItem('item3');
  console.log(Singleton.getItems());
});
require(["app/Singleton"], function(singletonFactory){
  var Singleton = singletonFactory.getInstance(false);
  Singleton.addItem('item4');
  console.log(Singleton.getItems());
});

In case you're interested in a full example, it's on Plunker.

Eventually you could wrap the factory as a plugin so that you could actually do something like:

require([ "app/Object!singleton", "app/Object!prototype" ], function() {

});

However I don't know if RequireJS also supports this (and if I'm understanding well it should be a generic story for both AMD loaders).



来源:https://stackoverflow.com/questions/22043096/switching-between-singleton-and-prototype-scope-using-requirejs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!