保证一个类仅有一个实例, 并且提供一个访问它的全局访问点
单例模式的思路是: 一个类能返回一个对象的引用 (并且永远是同一个) 和一个获得该实例的方法(静态方法, 通常使用 getInstance 名称). 那么当我们调用这个方法时, 如果类持有的引用不为空就返回该引用, 否者就创建该类的实例, 并且将实例引用赋值给该类保持的那个引用再返回. 同时将该类的构造函数定义为私有方法, 避免其他函数使用该构造函数来实例化对象, 只通过该类的静态方法来得到该类的唯一实例.
应用场景
日常开发中, 经常制作弹窗的时候我们需要一个半透明的遮罩层, 为了减少不必要的 dom 操作, 我们正确的思路应该是, 判断有没有生成过这个 model div 如果已经生成了就不必再次生成.
实现步骤
步骤 1 写一个生成 model div 的方法
- <style>
- .modal {
- position: fixed;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- opacity: .5;
- background: #000;
- z-index: 99;
- }
- </style>
- <script>
- function createModal () {
- const div = document.createElement('div');
- div.className = 'modal';
- document.body.appendChild(div);
- }
- createModal()
- createModal() // 调用两次 将会产生两个模态框
- </script>
复制代码
调用两次 createModal 方法将会产生在 body 上追加两个 div 很显然不是我们需要的结果, 我们需要增加一个变量判断是否已经调用过
根据单例模式的定义来实现
保证一个类仅有一个实例 new createModal()
并且提供一个访问它的全局访问点
createModal.getInstance
方法访问
- function createModal () {
- const div = document.createElement('div');
- div.className = 'modal';
- document.body.appendChild(div);
- }
- createModal.getInstance = function () {
- if (this.instace) {
- return this.instace;
- } else {
- this.instace = new createModal();
- return this.instace;
- }
- };
- const a = createModal.getInstance()
- const b = createModal.getInstance() // 调用两次 实例一次
- console.log(a === b) // true
复制代码
此段代码就根据单例模式的定义来用 js 实现了一个单例模式, 调用多次也只会实例一个 createModal , 生成一个模态框
惰性单例
由于 js 的特性, 可用闭包的形式保护一个私有变量, 让他来作为判断值, 并且惰性函数代表: 在需要的时候才创建对象实例, 而非在页面加载时就创建
- const createModal = (function(){
- let div;
- return function(){
- if(!div){
- div = document.createElement('div');
- div.className = 'modal';
- document.body.appendChild(div);
- }
- }
- })();
- createModal()
- createModal() // 调用两次 div 生成一次
复制代码
通过闭包, 保护了 div 变量, 在调用时候判断
通用模式
通过上面代码我们发现如果需要新建另外一个 div, 只能复制代码, 是否能想办法把 return 里生成 div 的方法分离出来呢.
创建一个 getSingle 方法 result 为判断变量
创建一个 createModal 的方法为具体执行代码, 并且返回一个 bool 值给 getSingle 中的 result 进行判断
- const getSingle = function (fn) {
- let result;
- return function () {
- return result || (result = fn.apply(this, arguments));
- }
- };
- const createModal = function () {
- const div = document.createElement('div');
- div.className = 'modal';
- document.body.appendChild(div);
- return div
- }
- const createSingleDiv = getSingle(createModal)
- const a = createSingleDiv()
- const b = createSingleDiv()
- console.log(a === b) // true
复制代码
这样就创建了一个 创建惰性单例的通用模式了
总结
单例模式在实际开发中应用很多, 特别是在框架设计, 合理利用可以提高性能.
来源: https://juejin.im/post/5b74cf5ae51d4560f178cff2