带构造函数的语义JavaScript单例
Semantic JavaScript singleton with constructor
所以我想要一个名为client
的类,它将是我用JavaScript编写的视频游戏的基础。
client
应该是一个只能有一个实例的类,但它的第一个创建应该在特定事件中由我自己设置,比如当用户单击"开始"按钮时。
我为自己创建了一个singleton类,并开始卸载它只是为了测试:
// Singleton class for the client
var client = (function() {
// Public methods
var _this = {
construct: function() {
delete _this.construct;
_this.director = new lime.Director(document.body, window.innerWidth, window.innerHeight); // Setup the rendering engine
}
}
return _this;
})();
// Fire when dependencies are loaded
window.onload = client.construct;
问题:
但我打算这是一个开源项目,在最后一行,client.construct
似乎是一个非常不寻常的约定。我该如何编写我的singleton类,使其使用new Client
构建,并且永远不能再构建?
首先:你确定你真的想这么做吗?对于大多数简单的情况,您可能根本不需要使用prototype
或new
关键字,而只需编写具有所需属性和方法的对象文字,或者如果需要稍微复杂的构造逻辑,则使用一次性函数创建对象。简洁是好的。
不过,我想有几种情况下,您可能想在JavaScript中创建一个"传统"的单例,比如延迟实例化,或者如果您使用的是涉及单例类原型的经典继承。
在这种情况下,您可能想尝试这种基于bfavaretto的方法,在这种方法中,类的用户希望通过调用Client.getSingletonInstance()
而不是new Client()
来获得Client对象,并且通过new
实例化Client发生在getSingletonInstance()
方法内部。
var Client = (function() {
// Our "private" instance
var instance;
// The constructor
function Client() {
// If it's being called again, throw an error
if (typeof instance != "undefined") {
throw new Error("Client can only be instantiated once.");
}
// initialize here
// Keep a closured reference to the instance
instance = this;
}
// Add public methods to Client.prototype
Client.prototype.myPublic = function() {
}
Client.getSingletonInstance = function() {
if (typeof instance == "undefined") {
return new this();
}
else {
return instance;
}
}
// Return the constructor
return Client;
})();
var c1 = Client.getSingletonInstance();
var c2 = Client.getSingletonInstance();
console.log(c1 == c2); // true
我更喜欢这种方式,因为在我看来,让类的用户调用new
但实际上没有得到一个新对象是有误导性的。
http://jsfiddle.net/hBvSZ/3/
您可以使用与常规面向对象语言中相同的模式:将实例存储在"私有"或"静态"属性中(我引用这些术语是因为它们并不完全适用于JavaScript)。在代码中,这将是这样的,使用"私有"属性来存储实例("静态"属性将是构造函数的属性):
var Client = (function() {
// Our "private" instance
var instance;
// The constructor
function Client() {
// If it's being called again, return the singleton instance
if(typeof instance != "undefined") return instance;
// initialize here
// Keep a closured reference to the instance
instance = this;
}
// Add public methods to Client.prototype
Client.prototype.myPublic = function() {
}
// Return the constructor
return Client;
})();
var c1 = new Client();
var c2 = new Client();
console.log(c1 == c2); // true
http://jsfiddle.net/hBvSZ/
类似这样的东西:
var Client = (function ClientClass(){
var instance;
// Constructor
function Client() {
if (instance) throw 'Already instantiated';
this.director = new lime.Director(...);
instance = true;
}
Client.prototype = {
// Public methods
};
return Client;
}());
这可能是您想要的:
var initialized = false;
function initialize() {
if (!initialized) {
window.client = new Client();
initialized = true;
}
}
window.onload = initialize;
您没有。在强类型语言中,singleton是通过具有私有构造函数并公开包含类的唯一实例的静态属性来生成的。防止第二次实例化的唯一方法是抛出异常,但这是更糟糕的设计。然而,您可能会延迟实例化您的对象:
// A wrapper function
var client = (function () {
var client = function() {
// Actual class
}
var instance = null;
// Property to return the instance
Object.defineProperty("instance", {
get: function () {
if (!instance) { instance = new client(); }
return instance;
}
}
return client;
})();
这是我最喜欢的单例实例模式,它简单明了:
var mySingleton = new function() {
// ...
}
所以你可以做:
var myClient = new function() {
this.director = null;
this.initialize = function() {
// Setup the rendering engine
this.director = new lime.Director(
document.body,
window.innerWidth,
window.innerHeight
);
}
}
window.onload = myClient.initialize();
来源:Alexander Podgorny 的Singleton模式
- 创建命名空间 Javascript 单例类的对象
- Javascript 单例模式
- 为什么这个javascript单例方法有效
- JavaScript 对象的单例行为
- Javascript 文字对象和单例模式
- JavaScript 中的单例实例范围混淆
- Javascript 单例继承
- Javascript/NodeJS是创建单例对象的最佳方式
- JavaScript,如何在使用单例时保持适当的封装
- 带构造函数的语义JavaScript单例
- 在javascript中还有其他实现单例模式的方法吗?
- 如何在javascript中基于参数创建对象的单例实例
- Javascript单例函数不工作
- JavaScript单例模式-差异
- _.bindAll()用于JavaScript单例方法
- JavaScript单例类型错误:为什么严格模式会标记这个
- 用这种方式实现Javascript单例模式有什么问题吗?
- 每个字符串的javascript单例对象
- 如何将Javascript单例更改为可以多次使用的单例
- Javascript单例:如何访问私有变量