600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > js设计模式 -- 单例模式

js设计模式 -- 单例模式

时间:2023-11-21 00:53:10

相关推荐

js设计模式 -- 单例模式

什么是单例模式?

保证一个类仅有一个实例,并提供一个访问它的全局访问点,这样的模式就叫做单例模式。

那么如何实现单例模式呢?

有两种方法:

1.我们现在把这段判断逻辑写成一个静态方法(其实也可以直接写入构造函数的函数体里):

2.我们也可以使用闭包来实现。

可以看出,在getInstance方法的判断和拦截下,我们不管调用多少次,SingleDog都只会给我们返回一个实例,s1和s2现在都指向这个唯一的实例。

工作实例

近年来,基于 Flux 架构的状态管理工具层出不穷,其中应用最广泛的要数 Redux 和 Vuex。无论是 Redux 和 Vuex,它们都实现了一个全局的 Store 用于存储应用的所有状态。这个 Store 的实现,正是单例模式的典型应用。

Vuex如何确保Store的唯一性

我们先来看看如何在项目中引入 Vuex:

通过调用Vue.use()方法,我们安装了 Vuex 插件。Vuex 插件是一个对象,它在内部实现了一个 install 方法,这个方法会在插件安装时被调用,从而把 Store 注入到Vue实例里去。也就是说每 install 一次,都会尝试给 Vue 实例注入一个 Store。

在 install 方法里,有一段逻辑和我们楼上的 getInstance 非常相似的逻辑:

楼上便是 Vuex 源码中单例模式的实现办法了,套路可以说和我们的getInstance如出一辙。通过这种方式,可以保证一个 Vue 实例(即一个 Vue 应用)只会被 install 一次 Vuex 插件,所以每个 Vue 实例只会拥有一个全局的 Store。

小结

这里大家不妨开个脑洞,思考一下:如果我在 install 里没有实现单例模式,会带来什么样的麻烦?

我们通过上面的源码解析可以看出,每次 install 都会为Vue实例初始化一个 Store。假如 install 里没有单例模式的逻辑,那我们如果在一个应用里不小心多次安装了插件:

失去了单例判断能力的 install 方法,会为当前的Vue实例重新注入一个新的 Store,也就是说你中间的那些数据操作全都没了,一切归 0。因此,单例模式在此处是非常必要的。

实现两道单例模式面试题

一、实现一个 Storage

实现Storage,使得该对象为单例,基于 localStorage 进行封装。实现方法 setItem(key,value) 和 getItem(key)。

静态方法版

闭包版本:

二、实现一个全局模态框

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>单例模式弹框</title></head><style>#modal {height: 200px;width: 200px;line-height: 200px;position: fixed;left: 50%;top: 50%;transform: translate(-50%, -50%);border: 1px solid black;text-align: center;}</style><body><button id='open'>打开弹框</button><button id='close'>关闭弹框</button></body><script>// 核心逻辑,这里采用了闭包思路来实现单例模式const Modal = (function() {let modal = nullreturn function() {if(!modal) {modal = document.createElement('div')modal.innerHTML = '我是一个全局唯一的Modal'modal.id = 'modal'modal.style.display = 'none'document.body.appendChild(modal)}return modal}})()// 点击打开按钮展示模态框document.getElementById('open').addEventListener('click', function() {// 未点击则不创建modal实例,避免不必要的内存占用;此处不用 new Modal 的形式调用也可以,和 Storage 同理const modal = new Modal()modal.style.display = 'block'})// 点击关闭按钮隐藏模态框document.getElementById('close').addEventListener('click', function() {const modal = new Modal()if(modal) {modal.style.display = 'none'}})</script></html>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。