原生JavaScript单例模式实战:原理与游戏开发应用
本文深入解析原生JavaScript中的单例模式,阐述其遵循的开闭原则及在减少系统开销、降低GC压力方面的优势。通过飞机大战地图管理的实际案例,对比简单实现与闭包封装两种写法,展示如何确保核心对象唯一性并优化资源利用。
本文通过具体实例解析原生JavaScript中单例模式的实际应用,旨在为读者提供清晰的参考与学习思路。
单例模式的核心原则与优势
核心原则遵循开闭原则(Open Close Principle),即对扩展保持开放,对修改保持关闭。在程序需要扩展功能时,应避免修改原有代码,从而实现“热插拔”效果。这一原则旨在提升程序的可扩展性,使其更易于维护和升级。此外,还需遵循单一职责原则:避免一个类承担多个导致变更的原因,确保每个类仅实现单一职责;若职责过多,则应将类进行拆分。
创建模式中的单例模式规定:某个类在整个系统中仅允许存在一个实例。其主要优点包括:1. 对于创建频繁或体积庞大的对象,单例模式能显著降低系统开销;2. 省去了重复的new操作,降低了内存使用频率,从而减轻垃圾回收(GC)的压力;3. 对于如交易所核心交易引擎等控制全局流程的关键类,若允许创建多个实例会导致系统混乱。例如,国家主席或飞机大战地图对象均只能有一个,使用单例模式能确保核心服务器独立控制整个流程。
单例模式的应用场景
以下是单例模式的具体应用场景分析。
在飞机大战游戏中,地图对象必须保持唯一实例;遮罩层若在项目中频繁创建和删除,会浪费大量资源,因此应在首次使用时创建实例,后续直接使用;放大镜功能同理,若频繁创建也是资源浪费,应采用单例模式在首次使用时创建,后续复用该实例。
基础应用与游戏实例
接下来介绍单例模式的基础应用代码结构。
<script>
let singleton = function (){
function Map(width,height) {
this.width = width;
this.height = height;
}
let instance;
return{
getIntence : function(width,height){
if(instance == undefined){
instance = new Map(width,height);
}else{
instance.width = width;
instance.height = height;
}
return instance;
}
}
}();
let m1 = singleton.getIntence(100,200);
let m2 = singleton.getIntence(200,300);
console.log(m1);//200 300
console.log(m2);//200 300
</script>
以飞机大战游戏为例,展示单例模式在实际项目中的具体应用方式。
重点分析地图模块的单例实现逻辑。
地图模块的闭包实现
let mapSingleton = (function(){
function Map(width,height,background){
this.domObj = null;//地图的div
this.moveBox = null;
this.width = width;
this.height = height;
this.background = background;
this.enemyPlanes = [];//敌机数组
this.myPlanes = [];//我方战机数组
this.createUI();
this.moveBg();
}
//853 600
Map.prototype.createUI = function() {
//1、地图的div
this.domObj = document.createElement("div");
this.domObj.style.cssText = `margin:20px auto;position: relative;width:${this.width}px;height:${this.height}px;overflow:hidden`;
document.body.appendChild(this.domObj);
//2、移动的div
this.moveBox = document.createElement("div");
this.moveBox.style.cssText = `position: absolute;
top:-1106px;
width: 480px;
height: 1706px;`;
this.domObj.appendChild(this.moveBox);
//3、图片
for(var i=0;i<2;i++){
let img01 = document.createElement("img");
img01.src = this.background;
img01.style.cssText = `display: block`;
this.moveBox.appendChild(img01);
}
//4、积分板:
this.scoreDom = document.createElement("div");
this.scoreDom.style.cssText = "position:absolute;left:0px;top:0px;width:100px;height:35px;z-index:999";
this.scoreDom.innerHTML = 0;
this.domObj.appendChild(this.scoreDom);
};
Map.prototype.moveBg = function(){
let top1 = -1106;
setInterval(()=>{
top1++;
if(top1>=-253){
top1 = -1106;
}
this.moveBox.style.top = top1+"px";
},50);
}
var instance;
return {
getInstance:function(width,height,background){
if(instance==undefined){
instance = new Map(width,height,background);
}else{
instance.width = width;
instance.height = height;
instance.background = background;
instance.domObj.style.width=this.width+"px";
instance.domObj.style.height=this.height+"px";
instance.moveBox.children[0].src=this.background;
instance.moveBox.children[1].src=this.background;
}
return instance;
}
}
})();
// 单例模式的总结
/*采用闭包原理和自调用原理,先进行自调用噶、返回闭包函数,让使用者调用,但只能创建一个实例对象,当要创建多个的时候 不会进行创建,最上面简单案例代码,如果要再次创建实例,会覆盖之前的数据,并且不会创建实例对象
为什么要采用闭包 防止使用者再次构造新对象 采用自调用之后 函数执行1次 在调用时 只需要使用return的函数就行 避免用户多次构造新对象*/
感兴趣的朋友可以使用在线HTML/CSS/JavaScript前端代码调试运行工具:http://tools.jb51.net/code/WebCodeRun测试上述代码运行效果。
更多关于JavaScript相关内容还可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
