why
- 在类中添加一个私有静态成员变量用于保存单例实例。
- 声明一个公有静态构建方法用于获取单例实例。
- 在静态方法中实现”延迟初始化”。该方法会在首次被调用时创建一个新对象,并将其存储在静态成员变量中。此后该方法每次被调用时都返回该实例。
- 将类的构造函数设为私有。类的静态方法仍能调用构造函数,但是其他对象不能调用。
检查客户端代码,将对单例的构造函数的调用替换为对其静态构建方法的调用。 ```typescript /**
- The Singleton class defines the
getInstance
method that lets clients access the unique singleton instance. */ class Singleton { private static instance: Singleton;
/**
- The Singleton’s constructor should always be private to prevent direct
- construction calls with the
new
operator. */ private constructor() { }
/**
- The static method that controls the access to the singleton instance. *
- This implementation let you subclass the Singleton class while keeping
just one instance of each subclass around. */ public static getInstance(): Singleton { if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance; }
/**
- Finally, any singleton should define some business logic, which can be
- executed on its instance. */ public someBusinessLogic() { // … } }
- The Singleton class defines the
/**
The client code. */ function clientCode() { const s1 = Singleton.getInstance(); const s2 = Singleton.getInstance();
if (s1 === s2) {
console.log('Singleton works, both variables contain the same instance.');
} else {
console.log('Singleton failed, variables contain different instances.');
} }
clientCode();
<a name="ffT7z"></a>
# 应用场景
<a name="BjB5d"></a>
## Vuex 中的单例模式
> 一个 Vue 实例只能对应一个 Store
```javascript
let Vue // 这个Vue的作用和楼上的instance作用一样
...
export function install (_Vue) {
// 判断传入的Vue实例对象是否已经被install过Vuex插件(是否有了唯一的state)
if (Vue && _Vue === Vue) {
if (process.env.NODE_ENV !== 'production') {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
}
return
}
// 若没有,则为这个Vue实例对象install一个唯一的Vuex
Vue = _Vue
// 将Vuex的初始化逻辑写进Vue的钩子函数里
applyMixin(Vue)
}
全局模态框
<!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>