设计模式:

单例模式
类似于单机游戏存档,下次进入游戏的时候,读取进度
- 特定类,访问时,始终返回同一个实例
- 单例
- 访问单例的方法, 或者直接 new 一个实例
应用:
当一个类的实例化过程消耗的资源过多,可用单例避免性能浪费
当项目中需要一个公共的状态,需要使用单例保证访问一致性
优点
1.在内存中只占一个实例,节省内存开支和实例化消耗,特别是开销较大的类 ,如数据库连接,不断销毁和重新实例化很浪费资源
- 可以解决对资源的多重占用,比如读写文件,只有一个实例,可避免对一个文件进行同时操作
- 可减少GC 浏览器中会卡顿较少,CPU资源占用更少
缺点
- 不容易扩展
- 与单一职责原则冲突
/**
* @description 单例模式 IIFE方式加闭包 本质是通过函数作用域的方式来隐藏内部作用域的变量
*/
const Singleton = (function() {
let _instance = null // 存储单例
const Singleton = function() {
if (_instance) return _instance // 判断是否已经有单例
_instance = this
this.init() // 初始化
return _instance
}
Singleton.prototype.init = function() {
this.foo = 'Singeton Pattern'
}
Singleton.getInstance = function() {
if (_instance) return _instance
_instance = new Singleton()
return _instance
}
return Singleton
})()
const vistor1 = new Singleton()
const vistor2 = new Singleton()
const vistor3 = new Singleton.getInstance()
console.log(vistor1 === vistor3) // true
----------------------------------------------------------------------------------------------------------------------------------
/**
* @description 单例模式 ES6的块级作用域 目的是为了 _instance隐藏内部变量
*/
let getInstance
{
let _instance = null
const Singleton = function() {
if (_instance) return _instance // 判断是否已经有单例
_instance = this
this.init() // 初始化
return _instance
}
Singleton.prototype.init = function() {
this.foo = 'Singeton Pattern'
}
getInstance = function() {
if (_instance) return _instance
_instance = new Singleton()
return _instance
}
}
const vistor1 = getInstance()
const vistor2 = getInstance()
----------------------------------------------------------------------------------------------------------------------------------
/**
* @description 单例 抽离 创建 和 功能逻辑
*/
class FuncClass {
constructor(bar) {
this.bar = bar
this.init()
}
init() {
this.foo = 'Single Pattern'
}
}
const Singleton = (function() {
let _instance = null
const ProxySingleton = function(bar) {
if (_instance) return _instance
_instance = new FuncClass(bar)
return _instance
}
ProxySingleton.getInstance = function(bar) {
if (_instance) return _instance
_instance = new Singleton(bar)
return _instance
}
return ProxySingleton
})()
const vistor1 = new Singleton('单例1')
const vistor2 = new Singleton('单例2')
const vistor3 = Singleton.getInstance()
----------------------------------------------------------------------------------------------------------------------------------
/**
* @description 单例模式 用ES6的proxy拦截 new
*/
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
}
function Singleton(FuncClass) {
let _instance
return new Proxy(FuncClass, {
construct(target, args) {
return _instance || (_instance = Reflect.construct(FuncClass, args))
}
})
}
const PersonInstance = Singleton(Person)
const person1 = new PersonInstance('张三', 20)
const person2 = new PersonInstance('李四', 25)
----------------------------------------------------------------------------------------------------------------------------------
/**
* @description 单例模式的应用 element-ui 的 loading
*/
import Vue from 'vue'
import loadingVue from './loading.vue // 自己写的Loading组件
const LoadingConstructor = Vue.extend(loadingVue)
let fullscreenLoading
const Loading = (options = {}) => {
if (options.fullscreen && fullscreenLoading) { // 如果之前创建国,直接返回
return fullscreenLoading
}
let _instance = new LoadingConstructor({
el: document.createElement('div'),
data: options
})
if (options.fullscreen) {
fullscreenLoading = _instance
}
return _instance
}
export default Loading
网友评论