美文网首页前端开发那些事儿
设计模式 - 单例模式

设计模式 - 单例模式

作者: vivianXIa | 来源:发表于2021-03-20 15:24 被阅读0次

    本来想一片文章写出所有的设计模式,但是我发现,以我的整理理解,篇幅估计不会太短,就每一种设计模式都单独写吧。平时不记录的话,合上电脑,一个星期后,相当于没看过。

    • 定义:当前进程中,当前类的实例有且只有一个。
      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

    相关文章

      网友评论

        本文标题:设计模式 - 单例模式

        本文链接:https://www.haomeiwen.com/subject/uvlwcltx.html