本来想一片文章写出所有的设计模式,但是我发现,以我的整理理解,篇幅估计不会太短,就每一种设计模式都单独写吧。平时不记录的话,合上电脑,一个星期后,相当于没看过。
- 定义:当前进程中,当前类的实例有且只有一个。
1:比如一个网站的登录,点击登录后弹出一个登录弹框,即使再次点击,也不会再出现一个相同的弹框。
2:又或者一个音乐播放程序,如果用户打开了一个音乐,又想打开一个音乐,那么之前的播放界面就会自动关闭,切换到当前的播放界面。这些都是单例模式的应用场景。
要实现一个单例模式,一个经典的方式是创建一个类,类中又一个方法能创建该类的实例对象,还有一个标记,记录是否已经创了过了实例对象。如果对象已经存在,就返回第一次实例化对象的引用。
es5实现方式
var Singleton = function(name) {
this.name = name;
//一个标记,用来判断是否已将创建了该类的实例
this.instance = null;
}
// 提供了一个静态方法,用户可以直接在类上调用
Singleton.getInstance = function(name) {
// 没有实例化的时候创建一个该类的实例
if(!this.instance) {
this.instance = new Singleton(name);
}
// 已经实例化了,返回第一次实例化对象的引用
return this.instance;
}
es6 实现方式
class Singleton {
constructor(name) {
this.name = name;
this.instance = null;
}
// 构造一个广为人知的接口,供用户对该类进行实例化
static getInstance(name) {
if(!this.instance) {
this.instance = new Singleton(name);
}
return this.instance;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>加油,奥里给</title>
</head>
<style>
/**
* index.scss
* - Add any styles you want here!
*/
body {
background: #f5f5f5;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.top-bar {
display: flex;
justify-content: space-between;
height: 40px;
line-height: 40px;
background-color: black;
}
.top-bar_left {
padding-left: 20px;
font-size: 22px;
color: #fff;
}
.top-bar_right {
display: flex;
color: #fff;
padding-right: 40px;
}
.top-bar_right div {
cursor: pointer;
}
.top-bar_right div:hover {
color: #ccc;
}
.login-btn {
margin-right: 20px;
}
.mask-layer {
display: flex;
justify-content: center;
position: absolute;
width: 100%;
height: 100%;
padding-top: 8%;
background-color: rgba(0, 0, 0, 0.3);
}
.login-wrapper {
width: 400px;
height: 200px;
padding-left: 20px;
background-color: #fff;
border: 1px solid #ccc;
}
.login-title {
display: flex;
justify-content: space-between;
padding: 10px 10px 0 0;
}
.close-btn {
cursor: pointer;
}
.user-input {
margin-top: 20px;
}
.login-text {
display: inline-block;
width: 60px;
}
.btn-wrapper {
display: flex;
margin-top: 20px;
}
.btn-wrapper button {
padding: 0 8px;
cursor: pointer;
}
.clear-btn {
margin-left: 10px;
}
</style>
<body>
<nav class="top-bar">
<div class="top-bar_left">
LTH BLOG
</div>
<div class="top-bar_right">
<div class="login-btn">登陆</div>
<div class="signin-btn">注册</div>
</div>
</nav>
<script>
class Login {
//构造器
constructor() {
this.init();
}
//初始化方法
init() {
//新建div
let mask = document.createElement('div');
//添加样式
mask.classList.add('mask-layer');
//添加模板字符串
mask.innerHTML =
`
<div class="login-wrapper">
<div class="login-title">
<div class="title-text">登录框</div>
<div class="close-btn">×</div>
</div>
<div class="username-input user-input">
<span class="login-text">用户名:</span>
<input type="text">
</div>
<div class="pwd-input user-input">
<span class="login-text">密码:</span>
<input type="password">
</div>
<div class="btn-wrapper">
<button class="confrim-btn">确定</button>
<button class="clear-btn">清空</button>
</div>
</div>
`;
//插入元素
document.body.insertBefore(mask, document.body.childNodes[0]);
//注册关闭登录框事件
Login.addCloseLoginEvent();
}
//静态方法: 获取元素
static getLoginDom(cls) {
return document.querySelector(cls);
}
//静态方法: 注册关闭登录框事件
static addCloseLoginEvent() {
this.getLoginDom('.close-btn').addEventListener('click', () => {
//给遮罩层添加style, 用于隐藏遮罩层
this.getLoginDom('.mask-layer').style = "display: none";
})
}
//静态方法: 获取实例(单例)
static getInstance() {
if (!this.instance) {
this.instance = new Login();
} else {
//移除遮罩层style, 用于显示遮罩层
this.getLoginDom('.mask-layer').removeAttribute('style');
}
return this.instance;
}
}
// /注册点击事件
Login.getLoginDom('.login-btn').addEventListener('click', () => {
console.log('zhe')
Login.getInstance();
})
</script>
</body>
</html>
购物车
class Cart{
constructor(){
this.list=[]
}
add(data){
this.list.push(data)
}
del(id){
this.list=this.list.filter(item=>{
if(item.id==id){
return false
}
return true
})
}
render(){
var dom=$('cartDom')
var html=''
for(let i=0;i<this.list.length;i++){
html+='<div>'+this.list[i].tit+'</div>'
}
dom.append(html)
}
static getInstance(){
if(!this.instance){
this.instance=new Cart();
}else{
console.log('已经创建过cart对象')
return
}
return this.instance
}
}
let cart=Cart.getInstance()
cart.add({id:1,tit:商品name.......})
cart.del(1)
闭包版
function StorageBase(){
StorageBase.prototype.getItem=function(){
return localStorage.getItem(key)
}
StorageBase.prototype.setItem=function(){
return localStorage.setItem(key,value)
}
}
const Storage1=(function(){
let instance=null
return function (){
if(!instance){
instance=new StorageBase()
}
return instance
}
})()
const storage3=new Storage1()
console.log(storage3)
const storage2=new Storage1()
storage3.setItem('name','张三')
storage3.getItem('name') //张三
storage2.getItem('name')//张三
单例模式得应用大家最熟悉得有vuex vue-router
实例:全局数据存储对象 (vuex)
function store(){
if(store.instance){
return store.instance
}
store.instance=this
}
//同
function store(){
if(!(this instanceof store)){
return new store()
}
}
上面得代码 可以new 也可以直接使用 ,这里使用了一个静态变量instance来记录是否有进行过实例化,如果实例化了就返回这个实例,如果没有实例化说明使第一次调用,就会把this赋给这个静态变量,因为是使用new 调用,这时候得this指向得就是实例化出来得对象,并且最后会隐式得返回this
var a=new store()
var b=store()
a==b
说的看到比较好的文章:
https://www.jianshu.com/p/7fa6ea107eff
网友评论