关闭

js设计模式之单例模式,javascript如何将一个对象设计成单例

时间: 2017-11-22阅读: 2785标签: 模式

单例模式是我们开发中一个非常典型的设计模式,js单例模式要保证全局只生成唯一实例,提供一个单一的访问入口,单例的对象可以不同于静态类,我们可以延迟单例对象的初始化,通常这种情况发生在我们需要等待加载创建单例的依赖。  


js单例的好处

1.在全局中只生成一个变量,减少全局变量的污染,同时也很好的解决了命名冲突。

2.只需新创建一次对象,减少对内存资源的占用。

3.减少系统加载的时间,遇到bug更容易排查。


js单例核心是确保只有一个实例,并提供全局访问  

在js中并没有类的说法,所谓的单一实例,就是指创建一个唯一的对象 ,这样的对象就满足了单例的条件,例如:

var demo={};

js单例在实际项目开发中通常采用使用闭包的形式,将变量封装到闭包内,只提供一个接口给外包使用。这里来实现一个功能通过单例创建div元素,例如:

var demo =(function(){
	var div;
	function init(){
	    div=document.createElement('div');
	    div.innerText="创建了一个div";
	    document.body.appendChild(div);
	}
	return function(){
        if(!div){
            init();
        }
        return div;
    }
})();
demo();//在页面上创建了一个div元素
demo();//已经创建了

这是一个最经典的惰性单例,如果实例不存在,通过一个方法创建一个实例,如果已经存在,则返回实例的引用。这里就说明了它和静态对象不同,可以被延迟生成,也就是说在我们需要的时候才创建对象实例,而非在页面加载时就创建。

 

但是在这里我们会发现一些问题:通过上面的方法只能实例一个div元素,如果需要创建多个就比较麻烦了。而且创建的实例和它的管理都放于一个函数demo中,这明显不能更好的扩展。所以需要把变化的封装起来,不变的隔离开,以便于我们程序的扩展性,例如:

var demo = function(fn){
    var elm;
    return function(){
        return elm || (elm = fn.apply(this, arguments));
    }
};
var initDiv=function(){
    var div=document.createElement('div');
	div.innerText="创建了一个div";  
    document.body.appendChild(div);
    return div;
};
var initP=function(){
    var p=document.createElement('p');
	p.innerText="创建了一个p";  
    document.body.appendChild(p);
    return p;
};
var a=demo(initDiv);
a();//创建了一个div
a();//已经存在了
var a_1=demo(initDiv);
a_1();//又创建了一个div
var b=demo(initP);
b();//又通过demo创建了p
b();//已经存在了


整理其它实现js单例的方法

方法1:

function Universe() {
    // 判断是否存在实例
    if (typeof Universe.instance === 'object') {
        return Universe.instance;
    }
    // 其它内容
    this.start_time = 0;
    this.bang = "Big";
    // 缓存
    Universe.instance = this;
    // 隐式返回this
}
// 测试
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true

方法2:

function Universe() {
    // 缓存的实例
    var instance = this;
    // 其它内容
    this.start_time = 0;
    this.bang = "Big";
    // 重写构造函数
    Universe = function () {
        return instance;
    };
}
// 测试
var uni = new Universe();
var uni2 = new Universe();
uni.bang = "123";
console.log(uni === uni2); // true
console.log(uni2.bang); // 123

方法3:

function Universe() {
    // 缓存实例
    var instance;
    // 重新构造函数
    Universe = function Universe() {
        return instance;
    };
    // 后期处理原型属性
    Universe.prototype = this;
    // 实例
    instance = new Universe();
    // 重设构造函数指针
    instance.constructor = Universe;
    // 其它功能
    instance.start_time = 0;
    instance.bang = "Big";
    return instance;
}
// 测试
var uni = new Universe();
var uni2 = new Universe();
console.log(uni === uni2); // true
// 添加原型属性
Universe.prototype.nothing = true;
var uni = new Universe();
Universe.prototype.everything = true;
var uni2 = new Universe();
console.log(uni.nothing); // true
console.log(uni2.nothing); // true
console.log(uni.everything); // true
console.log(uni2.everything); // true
console.log(uni.constructor === Universe); // true

方式4:

var Universe;
(function () {
    var instance;
    Universe = function Universe() {
        if (instance) {
            return instance;
        }
        instance = this;
        // 其它内容
        this.start_time = 0;
        this.bang = "Big";
    };
} ());
//测试代码
var a = new Universe();
var b = new Universe();
alert(a === b); // true
a.bang = "123";
alert(b.bang); // 123


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/153

关闭

Js修饰器模式

不会改变原有的对象,而是在其基础上进行拓展。实现原理:创建一个 A 类;A 类中的属性和方法使用 ES7 中的修饰器语法对类和类的属性增加功能

React组件设计模式-Render-props

写业务时,我们经常需要抽象一些使用频率较高的逻辑,但是除了高阶组件可以抽象逻辑,RenderProps也是一种比较好的方法。RenderProps,顾名思义就是将组件的props渲染出来。实际上是让组件的props接收函数,由函数来渲染内容。将通用的逻辑

js装饰者模式

装饰者模式:在不改变对象自身的基础上,动态地添加功能代码。 根据描述,装饰者显然比继承等方式更灵活,而且不污染原来的代码,代码逻辑松耦合。

vue-router的hash 模式和 history 模式

url 中带有#的便是 hash 模式,#后面是 hash 值,它的变化会触发 hashchange 这个事件。通过这个事件我们就可以知道 hash 值发生了哪些变化。

发布订阅模式与观察者模式

设计模式的定义是:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。通俗一点说,设计模式是在某种场合下对某个问题的一种解决方案。如果再通俗一点说,设计模式就是给面向对象软件开发中的一些好的设计取个名字。

前后端合作新模式

singsong:该模式主要对传统多页面应用构建的改进。关于 SPA(Single Page Application,单页应用程序)可以参考 SRR(Server-Side Render,服务端渲染)。在那个前端角色比较弱化的年代,页面主要以静态页面为主。

JS设计模式之Mixin(混入)模式

Mixin模式就是一些提供能够被一个或者一组子类简单继承功能的类,意在重用其功能。在面向对象的语言中,我们会通过接口继承的方式来实现功能的复用。

Js设计模式 - 单例模式实现及应用

单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者

js迭代器模式

迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。简单理解(白话理解):统一 “集合” 型数据结构的遍历接口,实现可循环遍历获取集合中各数据项

从一道面试题简单谈谈发布订阅和观察者模式

今天的话题是javascript中常被提及的「发布订阅模式和观察者模式」,提到这,我不由得想起了一次面试。记得在去年的一次求职面试过程中,面试官问我,你在项目中是怎么处理非父子组件之间的通信的?。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!