单例模式——面试真题
下面我们通过平时遇到的面试题继续巩固一下昨天学的单例模式。
- 描述
实现Storage,使得该对象为单例,基于 localStorage 进行封装。实现方法 setItem(key,value) 和 getItem(key)。
- 思路
首先我们单例模式最主要的就是有这么一个instance的东西,然后判断一下有就返回,没有就将instance指向当前对象。
class Storage {
static getInstance(){
//判断是否有一个实例
if(!Storage.instance){
// 若这个唯一的实例不存在,那么先创建它
Storage.instance = new Storage()
}
// 若这个唯一的实例存在,那么直接返回实例
return Storage.instance
}
setStoreItem(key, val){
localStorage.setItem(key, val)
}
getStoreItem(key){
return localStorage.getItem(key)
}
}
const storage1 = Storage.getInstance()
const storage2 = Storage.getInstance()
storage1.setItem('name', '李雷')
// 李雷
storage1.getItem('name')
// 也是李雷
storage2.getItem('name')
// 返回true
storage1 === storage2
当然你也可以通过原型和闭包来实现单例模式
function StorageBase(){}
StorageBase.prototype.getItem = function(key){
return localStorage.getItem(key)
}
StorageBase.prototype.setItem = function(key, value){
localStorage.setItem(key,value)
}
let Storage = (function(){
let instance = null
return function(){
if(!instance){
instance = new StorageBase()
}
return instance
}
})()
// 这里其实不用 new Storage 的形式调用,直接 Storage() 也会有一样的效果
const storage1 = new Storage()
const storage2 = new Storage()
storage1.setItem('name', '李雷')
// 李雷
storage1.getItem('name')
// 也是李雷
storage2.getItem('name')
// 返回true
storage1 === storage2
实现一个全局的模态框
- 思路
万变不离其踪,记住getInstance方法、记住instance变量、记住闭包和静态方法,这个题除了要多写点 HTML 和 CSS 之外,对大家来说完全不成问题。
<!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 = null
return 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>