JavaScript编程的单例设计模式讲解
在JavaScript开发中,单例模式是一个常见的设计模式。它可以保证一个类只有一个实例,并提供一个全局可访问该实例的访问点。
使用场景
当一个对象需要在整个应用程序中只有一个实例时,就可以考虑使用单例模式。如:
- 全局状态管理
- 路由管理
- 模态框管理
- 数据库连接池
- WebSocket连接管理等。
基本实现方式
let singleton = (function(){
let instance;
function init() {
// 私有方法和私有属性
let privateVar = 'I am private';
function privateMethod() {
console.log('This is private method');
}
// 公有方法和属性
return {
publicMethod: function() {
console.log('This is public method');
},
publicVar: 'I am public',
// 获取实例
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
}
}
return {
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
}
})();
let s1 = singleton.getInstance();
let s2 = singleton.getInstance();
console.log(s1 === s2); // true
以上代码使用了闭包和IIFE的特性,使得init函数只会执行一次并返回全局唯一的单例对象。
示例说明
示例1:全局状态管理
假设我们需要实现一个全局唯一的状态管理器,并且需要实现以下功能:
getState
方法获取当前状态setState
方法设置当前状态subscribe
方法订阅状态变更事件notify
方法通知所有订阅者状态变更事件
基于上述需求,我们可以使用单例模式实现一个状态管理器:
let stateManager = (function(){
let instance;
function init() {
let state = 0;
let subscribers = [];
function notifySubscribers() {
for(let i=0; i<subscribers.length; i++) {
subscribers[i]();
}
}
return {
getState: function() {
return state;
},
setState: function(s) {
state = s;
notifySubscribers();
},
subscribe: function(fn) {
subscribers.push(fn);
},
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
}
}
return {
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
}
})();
// 调用
let sm1 = stateManager.getInstance();
let sm2 = stateManager.getInstance();
console.log(sm1 === sm2); // true
sm1.subscribe(() => console.log('状态变更了:' + sm1.getState()));
sm1.setState(1);
sm1.setState(2);
示例2:WebSocket连接管理
假设我们需要实现一个全局唯一的WebSocket连接管理器,并且需要实现以下功能:
open
方法打开一个WebSocket连接,并自动重连send
方法向指定连接发送消息close
方法关闭指定连接getAll
方法获取所有连接状态
基于上述需求,我们可以使用单例模式实现一个WebSocket连接管理器:
let wsManager = (function(){
let instance;
function init() {
let connections = [];
function open(url) {
let conn = new WebSocket(url);
connections.push(conn);
conn.addEventListener('open', () => {
console.log('连接已建立:' + url);
});
conn.addEventListener('message', (e) => {
console.log('收到消息:' + e.data);
});
conn.addEventListener('close', () => {
console.log('连接已关闭:' + url);
setTimeout(() => open(url), 1000);
});
return conn;
}
function close(conn) {
conn.close();
connections.splice(connections.indexOf(conn), 1);
console.log('连接已关闭:' + conn.url);
}
function send(conn, message) {
conn.send(message);
console.log('向' + conn.url + '发送字符串消息:' + message);
}
function getAll() {
let result = [];
for (let i=0; i<connections.length; i++) {
result.push({ url: connections[i].url, readyState: connections[i].readyState });
}
return result;
}
return {
open: function(url) {
return open(url);
},
close: function(conn) {
return close(conn);
},
send: function(conn, message) {
return send(conn, message);
},
getAll: function() {
return getAll();
},
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
}
}
return {
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
}
})();
// 调用
let ws = wsManager.getInstance().open('ws://localhost:8080/');
wsManager.getInstance().send(ws, 'hello');
wsManager.getInstance().close(ws);
console.log(wsManager.getInstance().getAll());
上述两个示例分别实现了全局状态管理和WebSocket连接管理的功能,并都应用了单例模式来保证全局唯一性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript编程的单例设计模讲解 - Python技术站