Dojo Singleton 或者至少是静态方法/变量?

发布于 2024-10-05 14:04:03 字数 162 浏览 0 评论 0原文

有谁知道如何使 Dojo 类成为单例,或者至少如何在 dojo 类中创建静态方法或变量?

我目前通过为每个类设置一个全局变量和一个在该变量为空时设置该变量的方法来实现此目的,但这是一个蹩脚的解决方案。有一个单例类会好得多,因为可以从它继承,瞧,有一个单例:)

heinrich

does anyone know how to make a Dojo Class a singleton, or at least how to create a static method or variable in a dojo class?

I currently achieve this by having a global Variable for each class and a method that sets this variable if its null, but this is a crappy solution. Having a singleton class would be much nicer because one could inherit from it and voilá has a singleton :)

heinrich

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

何止钟意 2024-10-12 14:04:04
require(["dojo/_base/declare"], function (declare) {
var o =
    declare("com.bonashen.Singleton", null, {
        say : function (name) {
            console.log("hello," + name);
        }
    });
//define static getInstance function for com.bonashen.Signleton class.
console.debug("define getInstance function. ");
o.getInstance = function () {
    if (null == o._instance)
        o._instance = new o();
    return o._instance;
};});
require(["dojo/_base/declare"], function (declare) {
var o =
    declare("com.bonashen.Singleton", null, {
        say : function (name) {
            console.log("hello," + name);
        }
    });
//define static getInstance function for com.bonashen.Signleton class.
console.debug("define getInstance function. ");
o.getInstance = function () {
    if (null == o._instance)
        o._instance = new o();
    return o._instance;
};});
谁的新欢旧爱 2024-10-12 14:04:04

好吧,实际上没有人对 dojo 1.7+ AMD 给出一个好的答案(您可以在其他文件中要求,等等)
这就是我所拥有的:

define([
    "dojo/_base/declare",
], function(
    declare
) {
    var SingletonClass = declare("SingletonClass", [], {
        field: 47, 
        method: function(arg1) {
            return field*5;
        }
    });
    if (!_instance) {
        var _instance = new SingletonClass();
    }
    return _instance;
});

它似乎工作得很好,而且很有意义。

Okay, no one actually gave a good answer to this for dojo 1.7+ AMD (that you can require in other files, et cetera)
Here's what I have:

define([
    "dojo/_base/declare",
], function(
    declare
) {
    var SingletonClass = declare("SingletonClass", [], {
        field: 47, 
        method: function(arg1) {
            return field*5;
        }
    });
    if (!_instance) {
        var _instance = new SingletonClass();
    }
    return _instance;
});

It seems to work quite well, and make good sense.

时光病人 2024-10-12 14:04:04

如果您使用 dojo.declareClass 创建新类,则始终可以使用 new 运算符创建它的新实例。在Java中,单例是使用私有构造函数来实现的,但JavaScript不具备这种能力。所以你不能在JavaScript中创建类似Java的单例。

所以我创建单例的典型方法是:

if (typeof dojo.getObject('x.y.z') === 'undefined') {
    dojo.setObject('x.y.z', {
       //object definitions
    });
}

要创建静态变量,只需将该变量添加到 dojo 类对象中即可。

dojo.declare("x.y.ABC", {});
x.y.ABC.globalV = 'abc';

当与dojo.require一起使用时,JavaScript文件不会被dojo加载两次,因此您不需要检查变量是否存在。

If you use dojo.declareClass to create a new class, you can always use new operator to create a new instance of it. In Java, the singleton is implemented using private constructor, but JavaScript doesn't have this kind of capability. So you can not create the Java-like singleton in JavaScript.

So my typical way to create a singleton is :

if (typeof dojo.getObject('x.y.z') === 'undefined') {
    dojo.setObject('x.y.z', {
       //object definitions
    });
}

To create a static variable, just add the variable to the dojo class object.

dojo.declare("x.y.ABC", {});
x.y.ABC.globalV = 'abc';

When used with dojo.require, a JavaScript file won't be loaded twice by dojo, so you don't need to check the existence of a variable.

雨落星ぅ辰 2024-10-12 14:04:04

为什么不在构造函数中检查单例的创建,例如:

define(['dojo/_base/declare'], function (declare) {

    var singletonClass = declare(null, {

        someProperty: undefined,

        constructor: function () {
           if (singletonClass.singleton)
              throw new Error('only one instance of singletonClass may be created');

           this.someProperty = 'initial value';
        }
     });

     // create the one and only instance as a class property / static member
     singletonClass.singleton = new singletonClass();

     return singletonClass;
});

然后像这样使用它:

define(["app/singletonClass"], function(singletonClass) {
    var instance = singletonClass.singleton;  // ok
    var newInstance = new singletonClass();   // throws Error
});

Why not check for the creation of the singleton in the constructor function like:

define(['dojo/_base/declare'], function (declare) {

    var singletonClass = declare(null, {

        someProperty: undefined,

        constructor: function () {
           if (singletonClass.singleton)
              throw new Error('only one instance of singletonClass may be created');

           this.someProperty = 'initial value';
        }
     });

     // create the one and only instance as a class property / static member
     singletonClass.singleton = new singletonClass();

     return singletonClass;
});

Then use it like:

define(["app/singletonClass"], function(singletonClass) {
    var instance = singletonClass.singleton;  // ok
    var newInstance = new singletonClass();   // throws Error
});
空袭的梦i 2024-10-12 14:04:04

为什么要使用所有这些代码来创建 Dojo 单例?在模块中返回一个 new Class() 还不够吗?

例如:

模块:

define(["dojo/_base/declare"], function(declare){
var TestApp = declare(null, {
    constructor: function(){
        console.log("constructor is called only once");
        this.key = Math.random();
        console.log("generated key: "+this.key);
    },
    sayHello : function(){
        console.log("sayHello: "+this.key);
    }
});
return new TestApp();
});

测试:

    <script>
    require(['simplemodule.js'], function (amodule) {
        amodule.sayHello();
        console.log("first require");
    });

    require(['simplemodule.js'], function (amodule) {
        amodule.sayHello();
        console.log("second require");
    });


    require(['simplemodule.js'], function (amodule) {
        amodule.sayHello();
        console.log("third require");
    });

</script>

输出:

constructor is called only once simplemodule.js:4
generated key: 0.6426086786668748 simplemodule.js:6
sayHello: 0.6426086786668748 simplemodule.js:9
first require test.html:15
sayHello: 0.6426086786668748 simplemodule.js:9
second require test.html:20
sayHello: 0.6426086786668748 simplemodule.js:9
third require 

Why all this code to make a Dojo singleton? Is it not sufficient to return a new Class() in the module?

eg:

module:

define(["dojo/_base/declare"], function(declare){
var TestApp = declare(null, {
    constructor: function(){
        console.log("constructor is called only once");
        this.key = Math.random();
        console.log("generated key: "+this.key);
    },
    sayHello : function(){
        console.log("sayHello: "+this.key);
    }
});
return new TestApp();
});

test:

    <script>
    require(['simplemodule.js'], function (amodule) {
        amodule.sayHello();
        console.log("first require");
    });

    require(['simplemodule.js'], function (amodule) {
        amodule.sayHello();
        console.log("second require");
    });


    require(['simplemodule.js'], function (amodule) {
        amodule.sayHello();
        console.log("third require");
    });

</script>

output:

constructor is called only once simplemodule.js:4
generated key: 0.6426086786668748 simplemodule.js:6
sayHello: 0.6426086786668748 simplemodule.js:9
first require test.html:15
sayHello: 0.6426086786668748 simplemodule.js:9
second require test.html:20
sayHello: 0.6426086786668748 simplemodule.js:9
third require 
梦亿 2024-10-12 14:04:04

考虑 javascript 中的类实例并不总是有意义。如果您不想覆盖任何先前定义的对象,您可以执行以下操作:

something.myObject = something.myObject || {
    //Here you build the object
}

因此,您将获得先前定义的 something.myObject (如果它已定义),或者(使用 ||)您使用 {} 构建新对象。对对象的任何修改都会保留,因为您只构建一个新对象(如果它之前是一个假值)。

Thinking about instances of classes in javascript does not always make sense. If you do not want to override any previous defined object, you can do the following:

something.myObject = something.myObject || {
    //Here you build the object
}

So, you would get the previous defined something.myObject if it is already defined, or (using ||) you build the new object with {}. Any modifications to the object remain, as you only build a new object, if it is a falsy value before.

满天都是小星星 2024-10-12 14:04:04

这就是我在 Dojo 中创建单例的方法:

var makeSingleton = function (aClass) {
    aClass.singleton = function () {
        var localScope = arguments.callee;
        localScope.instance = localScope.instance || new aClass();
        return localScope.instance;
    };
    return aClass;
};

makeSingleton(dojo.declare(...));

然后,使用它:

myClass.singleton()

This is how I make my singletons in Dojo:

var makeSingleton = function (aClass) {
    aClass.singleton = function () {
        var localScope = arguments.callee;
        localScope.instance = localScope.instance || new aClass();
        return localScope.instance;
    };
    return aClass;
};

makeSingleton(dojo.declare(...));

Then, to use it:

myClass.singleton()
煞人兵器 2024-10-12 14:04:04

考虑按以下方式声明单个tone对象(Dojo 1.10),它使用闭包来保留模块中实例的引用并将方法添加到函数的原型中。

可以在此处找到有关该主题的好文章。

define([

], function (

    ) {
    'use strict';
    var _instance;
    function _SingleTone() {
    }
    _SingleTone.prototype = {
        init: function () {
        }
    };
    return function _getSingleton() {
        return (_instance = (_instance || new _SingleTone()));
    };
});

Consider declaring a single tone object in the following manner (Dojo 1.10), it uses a closure to keep reference of an instance in the module and add methods to the prototype of a function.

A good article on the topic can be found here.

define([

], function (

    ) {
    'use strict';
    var _instance;
    function _SingleTone() {
    }
    _SingleTone.prototype = {
        init: function () {
        }
    };
    return function _getSingleton() {
        return (_instance = (_instance || new _SingleTone()));
    };
});
初相遇 2024-10-12 14:04:03

作为背景信息,以下文章很好地定义了 JavaScript 中单例对象的模式:
http://kaijaeger.com/articles/the-singleton-design -pattern-in-javascript.html

为了Dojo-tize这个,使用1.7+我们需要在闭包中捕获原始构造函数,以便闭包之外的任何人都无法访问原始构造函数并提供
访问器方法总是返回相同的实例,无论谁尝试获取
引用它...

将“类”构造函数转换为单例作为可共享、可重用的代码片段的方法也是有意义的。我在 Dojo 中的偏好是有这个
作为它自己的“模块”作为实用方法(不是 Dojo 类对象),所以我们开始...

MakeSingleton.js

define(['dojo/_base/lang'], function(lang)
{
  return function(ctor) {   // not defining a class, just a utility method.
      var singletonCtor,    // our singleton constructor function.
          instance = null;  // singleton instance provided to any clients.

      // define the singleton constructor with accessor method.
      // (captures 'ctor' parameter and 'instance' variable in a function
      //  closure so that they are available whenever the getInstance() method
      //  on the singleton is called.)
      singletonCtor = new function() {       // note: 'new' is important here!!
          this.getInstance = function() {    // our accessor function
              if (!instance) {               // captures instance in a closure
                instance = new ctor();       // create instance using original ctor.
                instance.constructor = null; // remove instance's constructor method
              }                              //  so you cannot use new operator on it!!
              return instance;               // this is our singleton instance.
          }  
      };  

      // Since we are working with Dojo, when declaring a class object, if you
      // provide a 'className' as the first parameter to declare(...), Dojo will
      // save that value in the 'declaredClass' property on the object's prototype...
      // ... and adds a reference to that constructor function in the global namespace
      // as defined by the 'className' string.
      //
      // So if 'declaredClass' has a value, we need to close the hole by making
      // sure this also refers to the singleton and not the original constructor !!
      //
      if (ctor.prototype && ctor.prototype.declaredClass) {
        lang.setObject(ctor.prototype.declaredClass, singletonCtor);
      }

      // return the singleton "constructor" supports only a getInstance() 
      // method and blocks the use of the 'new' operator.
      return singletonCtor;

  }; // return "MakeSingleton" method
};  // define(...)

那么当我们想要定义时,我们如何在 Dojo 1.7+ 中使用它Singleton 类对象?
非常简单,因为我们已经完成了上面的繁重工作...

MySingletonClass.js

define(['dojo/_base_declare', 'MakeSingleton'], 
       function(declare, MakeSingleton)
{
    return MakeSingleton( declare('MySingletonClass', [...], {
                          // Define your class here as needed...
                        }));  
});

那么这里发生了什么...
调用declare(...) 的结果直接传递到MakeSingleton(...) 实用程序中
方法,因此 Dojo 创建的原始类构造函数(Function)永远不会公开,并且如果“className”被传递到 declare(...) 中,MakeSingleton 也会确保
不是原始构造函数,而是单例对象。此外,出口自
这个模块也是单例对象(MakeSingleton的返回值),所以Dojo
加载器仅在运行工厂方法后才有对单例的引用。这
原始构造函数类是在单例对象的闭包中捕获的,因此
其他人无法访问它并创建额外的实例...
我们确实有一个单身人士

那么我们如何访问这个单例......如果您在使用时没有指定“className”
声明您的类,获取它的唯一方法是通过模块依赖项引用。如果您确实指定了“className”,如上面的示例(耻辱,耻辱),您可以访问它
来自全局名称空间(这不是 Dojo 的方向,使用模块依赖项引用)。

调用 MakeSingleton.js 实用程序模块的导出方法的结果是
对象有一个名为 getInstance() 的方法。 getInstance() 将创建
在第一次调用时返回原始类对象的实例,并在每次后续调用时返回相同的实例。如果您尝试在单例类上使用“new”,则会生成错误。如果您尝试在全局命名空间中的引用上使用“new”(如果
您提供了一个“className”来声明),它将生成错误。 唯一方法
获取实例的方法是调用单例的 getInstance() 方法。

SomeOtherModule.js

define(['dojo/_base/declare', 'MySingletonClass'],
       function(declare, MySingletonClass) 
{
    return declare(null, { 
        mySingleton: null,    // here we will hold our singleton reference.
        constructor: function(args) {
            ...
            // capture the singleton...
            mySingleton = MySingletonClass.getInstance();
            ... 
            mySingleton.doSomething(...);
        };

        mySpecialSauce: function(...) {
            mySingleton.doSomethingElse(...);
        };

        moreSauce: function(...) {
            var x;
            x = MySingletonClass.getInstance(); // gets same instance.
            x = new window.MySingletonClass();  // generates an error!!
            x = new MySingletonClass();         // generates an error!!
            // Dojo's loader reference generates an error as well !!
            x = new require.modules['MySingletonClass'].result(); 
        };
    });
});

有多少模块、类、脚本元素等获得对
单例对象,它们都将引用同一个实例,并且“新”实例不能
创建的。

The pattern for a singleton object in JavaScript is defined pretty well by the following article as background information:
http://kaijaeger.com/articles/the-singleton-design-pattern-in-javascript.html

To Dojo-tize this, using 1.7+ we need to capture the original constructor function in a closure so that nobody outside of the closure has access to the original and provide an
accessor method that always returns the same instance, no matter who tries to get a
reference to it...

It also makes sense to have the method that turns a "class" constructor Function into a singleon as a shareable, reuseable, piece of code. My preference in Dojo, is to have this
as its own "module" as a utility method (not a Dojo class object), so here we go...

MakeSingleton.js

define(['dojo/_base/lang'], function(lang)
{
  return function(ctor) {   // not defining a class, just a utility method.
      var singletonCtor,    // our singleton constructor function.
          instance = null;  // singleton instance provided to any clients.

      // define the singleton constructor with accessor method.
      // (captures 'ctor' parameter and 'instance' variable in a function
      //  closure so that they are available whenever the getInstance() method
      //  on the singleton is called.)
      singletonCtor = new function() {       // note: 'new' is important here!!
          this.getInstance = function() {    // our accessor function
              if (!instance) {               // captures instance in a closure
                instance = new ctor();       // create instance using original ctor.
                instance.constructor = null; // remove instance's constructor method
              }                              //  so you cannot use new operator on it!!
              return instance;               // this is our singleton instance.
          }  
      };  

      // Since we are working with Dojo, when declaring a class object, if you
      // provide a 'className' as the first parameter to declare(...), Dojo will
      // save that value in the 'declaredClass' property on the object's prototype...
      // ... and adds a reference to that constructor function in the global namespace
      // as defined by the 'className' string.
      //
      // So if 'declaredClass' has a value, we need to close the hole by making
      // sure this also refers to the singleton and not the original constructor !!
      //
      if (ctor.prototype && ctor.prototype.declaredClass) {
        lang.setObject(ctor.prototype.declaredClass, singletonCtor);
      }

      // return the singleton "constructor" supports only a getInstance() 
      // method and blocks the use of the 'new' operator.
      return singletonCtor;

  }; // return "MakeSingleton" method
};  // define(...)

So how do we use this in Dojo 1.7+ when we want to define a Singleton class object?
Pretty easy since we have already done the heavy lifting above...

MySingletonClass.js

define(['dojo/_base_declare', 'MakeSingleton'], 
       function(declare, MakeSingleton)
{
    return MakeSingleton( declare('MySingletonClass', [...], {
                          // Define your class here as needed...
                        }));  
});

So what is going on here...
The result of calling declare(...) is passed directly into the MakeSingleton(...) utility
method, so the original class constructor (Function) created by Dojo is never made public, and if a 'className' was passed into declare(...), MakeSingleton has also made sure that
is not the original constructor, but the singleton object. Furthermore, the export from
this module is also the singleton object (MakeSingleton's return value), so the Dojo
loader only has a reference to the singleton after running the factory method. The
original constructor class is captured within a closure of the singleton object, so
nobody else can get to it and create an additional instance...
we truly have a singleton.

So how do we get access to this singleton... If you do not specify a 'className' when you
declare your class, the only way to get at it is through a module dependency reference. If you did specify a 'className' as in the example above (shame, shame), you can access it
from the global name space (which is NOT the way Dojo is headed, use the module dependency reference).

The result of calling the exported method of the MakeSingleton.js utility module is an
object that has a single method on it called getInstance(). getInstance() will create
an instance of the original class object on its first call, and return that same instance on every successive call. If you try to use 'new' on the singleton class, it will generate an error. If you try to use 'new' on the reference in the global namespace (if
you provided a 'className' to declare), it will generate an error. The only way to
get a hold of the instance is to call the singleton's getInstance() method.

SomeOtherModule.js

define(['dojo/_base/declare', 'MySingletonClass'],
       function(declare, MySingletonClass) 
{
    return declare(null, { 
        mySingleton: null,    // here we will hold our singleton reference.
        constructor: function(args) {
            ...
            // capture the singleton...
            mySingleton = MySingletonClass.getInstance();
            ... 
            mySingleton.doSomething(...);
        };

        mySpecialSauce: function(...) {
            mySingleton.doSomethingElse(...);
        };

        moreSauce: function(...) {
            var x;
            x = MySingletonClass.getInstance(); // gets same instance.
            x = new window.MySingletonClass();  // generates an error!!
            x = new MySingletonClass();         // generates an error!!
            // Dojo's loader reference generates an error as well !!
            x = new require.modules['MySingletonClass'].result(); 
        };
    });
});

It does not matter how many modules, classes, script elements, etc. get a reference to the
singleton object, they will all be referring to the same instance and 'new' ones cannot be
created.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文