js设计模式之单例模式

一.什么是单例模式

单例模式顾名思义是在该模式下,函数调用时如果实例没有创建就新创建一个实例,再次调用该函数返回已经创建的实例。

二.单例模式的通用实现

在实现单例的过程中,我们通常使用两个函数,第一个函数来实现单例控制逻辑,第二个函数用来创建实例

// 管理单例
function getSingleton(fn) {
    let instance;
    return function() {
        return instance || (instance = fn.apply(this, arguments))  
    }
}
// 创建弹窗
function createModal(option = {}) {
   	let div = document.createElement('div')
    div.innerHTML = option.text || '弹窗'
    div.className = 'modal'
    div.style.display = 'none'
    document.body.appendChild(div)
    // 这里不直接return div 而是返回一个对象,只暴露想要暴露的
    return {
        option,
        show() {
            div.style.display = 'block'
        },
     }
}
// 创建弹窗单例
let createSingletonModal = getSingleton(createModal)
document.querySelector('.modal-btn').addEventListener('click',  () => {
    createSingletonModal({text: '我是弹窗'}).show()
    setTimeout(() => createSingletonModal({text: '我是弹窗2'}).show(), 9000);
})

上述实现了单例的功能,但是仍然有缺陷,在实际的项目中,modal框每次弹出的内容可能都会有所不同,对上述方法进行改进,暴露出setContent方法,重新设置option

 // 管理单例
   function getSingleton(fn) {
        let instance;
        return function () {
            return instance && 
            instance.setContent.apply(instance, arguments) || 
            (instance = fn.apply(this, arguments))
        }
    }

    // 创建弹窗
    function createModal(option = {}) {
        let div = document.createElement('div')
        div.innerHTML = option.text || '弹窗'
        div.className = 'modal'
        div.style.display = 'none'
        document.body.appendChild(div)
        return {
            option,
            show() {
                div.style.display = 'block'
            },
            setContent(option) {
                if (div.innerText === option.text) return this
                div.innerHTML = option.text || '弹窗'
                return this
            }
        }
    }

    // 创建弹窗单例
    let createSingletonModal = getSingleton(createModal);


    document.querySelector('.modal-btn').addEventListener('click', () => {
		let m1 = createSingletonModal({ text: '我是弹窗1' })
        m1.show()
        setTimeout(() => {
            let m2 = createSingletonModal({ text: '我是弹窗2' })
            m2.show()
            console.log(m1 === m2);  // true
        }, 3000);
    })

三.总结

本文首先介绍了通用单例实现,以页面modal为例,在首次实现中,我们发现对于不同的text,弹窗显示的值都是相同的,因此我们提供了一个setContent方法来实现内容的更新。
但这样做也有一点缺陷,就是getSingleton方法本义只是控制单例逻辑的实现,但修改后还调用单例内部的方法用来实现视图的更新

todo: 用一种更优雅的方法来实现视图的更新,在getSingleton不调用setContent方法来实现。

demo源码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值