原生JavaScript单例模式实战:原理与游戏开发应用

作者:纸飞机

时间:2026-10-23

浏览:455

本文深入解析原生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程序设计有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章