(设计模式)2.单例模式

605 阅读2分钟

说明:每天一个设计模式,成功奖励自己买个小册学习o(╥﹏╥)o
PS:学习自---掘金的JavaScript 设计模式核⼼原理与应⽤实践小册

1.概念

保证一个类仅有一个实例,并提供一个访问它的全局访问点

2.代码案例
  • a.通过类定义方式实现
/**
 * 游戏说明:
 * 1.当我们玩王者荣耀的时候,都会有一个游戏金币。
 * 2.当我们进入游戏不同页面的时候我们都能够获得这个游戏金币,而不是重新请求获得
 * 3.哈哈哈强制和vuex中概念类似
 * 
*/
class Game {
    enter() {
        console.log('进入游戏画面');
    }
    // 静态方法获取对象
    static getGame() {
        // 判断是否创建实例了
        if(!Game.obj) {
            Game.obj = new Game()
        }
        return Game.obj;
    }
}
// 获取的对象都是同一个的对象
const game1 = Game.getGame();
const game2 = Game.getGame();
const game3 = Game.getGame();
console.log(game1 === game2); // true
console.log(game2 === game3); // true
  • b.通过闭包的方式实现
function Game() {
}
Game.getGame = (function(){
    let obj = null;
    return function(){
        if(!obj){
            obj = new Game()
        }
        return obj;
    }
})();
const game1 = Game.getGame();
const game2 = Game.getGame();

console.log(game1 === game2); // true
3.面试题
  • a.实现一个Storage

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

1).静态方法实现
PS:案例需要结合html页面实现

/**
 * 说明:
 * 1.首先创建保证只有一个实例的对象
 * 2.通过这个对象set和get值,结合localStorage
 */
class Storage {
    static getInstance() {
        if(!Storage.instance){
            Storage.instance = new Storage()
        }
        return Storage.instance
    }
    // 设置值
    setItem(key, value) {
        return localStorage.setItem(key, value)
    }
    // 获取值
    getItem(key) {
        return localStorage.getItem(key)
    }
}
const storage1 = Storage.getInstance();
const storage2 = Storage.getInstance();
storage1.setItem('age', 12);
console.log(storage2.getItem('age'))  // 12
console.log(storage2.getItem('age'))  // 12
storage2.setItem('age', 13);
console.log(storage1.getItem('age'))  // 13

2).闭包版

function StorageBase () {
}
StorageBase.prototype.getItem = function (key){
    return localStorage.getItem(key)
}
StorageBase.prototype.setItem = function (key, value){
    return localStorage.setItem(key, value)
}

const Storage = (function(){
    let instance = null;
    return function(){
        if(!Storage.instance) {
            instance = new StorageBase();
        }
        return instance;
    }
})()

const storage1 = new Storage();
const storage2 = new Storage();
storage1.setItem('age', 12);
console.log(storage2.getItem('age'))  // 12
console.log(storage2.getItem('age'))  // 12
storage2.setItem('age', 13);
console.log(storage1.getItem('age'))  // 13

  • b.实现一个全局的模态框 1).静态方法实现
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>单例模式弹框</title>
    <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>
</head>
<body>
    <button id="open">打开弹窗</button>
    <button id="close">关闭弹窗</button>
    <script>
        class Modal {
            static getModal() {
                if(!Modal.modal) {
                    Modal.modal = document.createElement('div');
                    Modal.modal.innerHTML = '我是一个全局唯一的Modal'
                    Modal.modal.id = 'modal'
                    Modal.modal.style.display = 'none'
                    document.body.appendChild(Modal.modal)

                }
                return Modal.modal;
            }
        }
        document.getElementById('open').addEventListener('click', function() {
            const modal = Modal.getModal();
    	    modal.style.display = 'block'
        })
        document.getElementById('close').addEventListener('click', function() {
            const modal = Modal.getModal();
            if(modal) {
                modal.style.display = 'none'
            }
        })
    </script>
</body>
</html>

2).闭包实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>单例模式弹框</title>
    <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>
</head>
<body>
    <button id="open">打开弹窗</button>
    <button id="close">关闭弹窗</button>
    <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() {
            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>
</body>
</html>