zoukankan      html  css  js  c++  java
  • js常见的设计模式一

      1.观察者模式

        定义一些一对多的关系,将一系列的观察者对目标函数感兴趣,将自己添加进目标函数,当目标函数状态发生改变时,发送通知,以此通知附加在目标上的观察者

    /* 目标 */
    class subject {
        constructor () {
            this.handlers = []
        }
        addhanler (fn) {
            this.handlers.push(fn)
        }
        notity () {
            this.handlers.forEach(hanlder=>{
                hanlder.update()
            })
        }
    }
    /* 观察者 */
    class observer {
        constructor (name) {
            this.name = name
        }
        update () {
            console.log(this.name)
        }
    }
    let sub = new subject();
    
    sub.addhanler(new observer('czklove'))
    sub.addhanler(new observer('czklove1'))
    sub.addhanler(new observer('czklove2'))
    
    sub.notity()

      2.发布订阅者模式

        订阅者A和发布者B是通过中间件关联起来的,他们没有直接的交流

    /* 
        pusher 为发布订阅者模式的中间件
        相对于观察者模式对了一个中间件,观察者模式,目标是观察者联系紧密
        而发布订阅者模式,发布者和订阅者完全没有关系
     */
    let pusher = {
        clentlist: {},
        addhandler (key,fn) {
            if(!this.clentlist[key]) {
                this.clentlist[key] = []
            }
            this.clentlist[key].push(fn)
        },
        notify (key,...args) {
            if(this.clentlist[key]) {
                this.clentlist[key].forEach(hanlder=>{
                    hanlder(...args)
                })
            }
        }
    }
    pusher.addhandler('click',(val)=>{
        console.log('1'+val)
    })
    pusher.addhandler('click',(val)=>{
        console.log('2'+val)
    })
    pusher.addhandler('click',(val)=>{
        console.log('3'+val)
    })
    pusher.notify('click','czklove')

      3.中间件模式

        中间件模式在js中也广泛引用,如node的express框架,axios源码中的请求拦截器和访问拦截器,我们实现一个简单的中间件

    /* 中间件模式 */
    
    class app {
        constructor () {
            this.hanlders = []
        }
        /* 使用use将需要执行的目标插入执行队列中 */
        use (fn) {
            this.hanlders.push(fn)
        }
        /* 开始执行入口 */
        run () {
            /* done为当前的执行函数
                如果已经执行进入了,则改为flase,
                查看回调hanlders是否会调用next,
                如果调用next则继续调用下一个回调函数
                如果没有next则执行到此为止
             */
            let done = true
            function next () {
                console.log('执行了next')
                done = true
            }
            /* 待执行的队列 */
            this.hanlders.forEach(hanlder => {
                if (!done) {
                    return
                } else {
                    done = false
                    hanlder(next)
                }
            });
            if(done) {
                this.callback();
            }
        }
        /* 最终的回调执行函数 */
        callback () {
            console.log('我们最终需要执行的函数')
        }
    }
    let p = new app();
    
    p.use(next=> {
        console.log('中间件1')
        next()
    })
    p.use(next=> {
        console.log('中间件2')
        next()
    })
    p.use(next=> {
        console.log('中间件3')
        next()
    })
    p.run()
    (注,p传入的回调函数,next只是一个形参,不一定非要是next)

    中间件1
    执行了next
    中间件2
    执行了next
    中间件3
    执行了next
    我们最终需要执行的函数

    如果我们注释掉中间件2的next 则输出的结果为

    中间件1
    执行了next
    中间件2

      4.单列模式

        对象在全局只有一个实列对象

        

    /* 单列模式 */
    /*  */
    function createperson () {
        class person {
            constructor (name,age) {
                this.name = name;
                this.age = age;
            }
        }
        var person1 = null; 
        return function (name,age) {
            if (person) {  
            } else {
                person1 = new person(name,age)
            }
            return person1
        }
    
    }
    let creatp = createperson();
    
    /* 创建person的实列对象p1 */
    let p1 = creatp('czklove','28')
    /* 创建person的实列对象p2 */
    let p2 = creatp('czklove','29')
    console.log(p1===p2)
    /* 最终输出true */
    /* person全局只能有一个实列对象 */

      5 工厂模式

        根绝不同的要求,生产出不同的实例对象

    /* 工厂模式 */
    /* 很简单,大概就是下面这个样子,根据传入的参数,生成对应的实例对象 */
    function createobj (type) {
        function cj1 () {
            this.name = 'czklove',
            this.age = '17'
        }
        function cj2 () {
            this.name = 'czklove',
            this.age = '18'
        }
        function cj3 () {
            this.name = 'czklove',
            this.age = '19'
        }
    
        switch (type) {
            case 'cj1' :
                return new cj1();
            case 'cj2' :
                return new cj2();
            case 'cj3' :
                return new cj3();
            default:
                return new cj1();
        }
    } 
    console.log(createobj('cj1'))
    console.log(createobj('cj2'))
    console.log(createobj('cj3'))

    //cj1

     //{name: "czklove", age: "17"}
       //{name: "czklove", age: "18"}
     
       //{name: "czklove", age: "19"}

      都是一些比较简单的模式,好多都用到了js中的闭包。好好理解闭包真的特别重要

  • 相关阅读:
    RF手持配置问题
    S4系统编辑屏幕报错
    【SAP】日志表CDHDR和CDPOS
    VA01隐藏销售凭证流的金额
    ABAP MODIFY SCREEN
    解决SMARTFORMS 中table 控件单行跨页的问题
    golang json 性能分析
    【高性能】GO 高性能专题
    9千万次循环 从2分3秒 优化到 7.3秒的过程 GO语言
    IDE 插件开发 相关点 -------------- Vscode debug protocol JDWP DAP
  • 原文地址:https://www.cnblogs.com/czkolve/p/10914498.html
Copyright © 2011-2022 走看看