设计模式读书笔记之外观模式、惰性模式

  • 外观模式

  由于子系统或者程序组成比较复杂而提供一个高层面的接口,该模式对外有一个统一的接口,可以在使用的时候不用知道内部的详细逻辑,降低原有系统的使用复杂度。较多用在处理兼容不同平台的问题。

外观模式的一个经典实现:addEvent函数 

function addEvent(dom, type, fn) {
  if (dom.addEventListener) {     dom addEventListener(type, fn, false)   }else if (dom.attactEvent) {     dom.attachEvent('on' + type, fn)   }else {     dom['on' + type]   } }
const myInput = document.getElementById('myInput')
addEvent(myInput, 'click', function() {
  console.log('绑定事件')
})

 onclick和click绑定事件的区别:

  onclick可以被覆盖,当需要同时执行多个事件时,需要使用addEventListener,  addEventListener可以在同一dom上绑定多个事件,并且不会覆盖,在触发click事件时,绑定事件按顺序执行。

导出文件,用于兼容不同浏览器,调用时只需要调用暴露出来的最外层接口即可。

export function exportDownload(exportData, suffix, fileName) {
  const blob = new Blob([exportData])
  if ('download' in document.createElement('a')) {
    const elink = document.createElement('a')
    elink.style.display = 'none'
    elink.download = fileName + suffix
    elink.href = URL.createObjectURL(blob)
    document.body.appendChild(elink)
    elink.click()
    URL.revokeObjectURL(elink.href)
    document.body.removeChild(elink)
  } else {
    navigatoe.msSaveBlob(blob, new Date().getTime() + suffix)
  }
}

 一键遥控

class Light {
    on() {
        console.log('打开灯')
    }
    off() {
        console.log('关掉灯')
    }
}

class Computer {
    on() {
        console.log('打开电脑')
    }
    off() {
        console.log('关掉电脑')
    }
}

class Aircondition {
    on() {
        console.log('打开空调')
    }
    off() {
        console.log('关掉空调')
    }
}

let light = new Light(),
    computer = new Computer(),
    aircondition = new Aircondition()

class Facade {
    on() {
        light.on()
        computer.on()
        aircondition.on()
    }
    off() {
        light.off()
        computer.off()
        aircondition.off()
    }
}

let facade = new Facade()
facade.on()
// 打开灯
// 打开电脑
// 打开空调
facade.off()
// 关掉灯
// 关掉电脑
// 关掉空调

 

  • 惰性模式

  减少每次代码执行时重复执行的某些分支判断,通过对对象的重定义来屏蔽原对象中的分支判断,提高网站性能。

针对上文中的不同浏览器的事件注册方法,每次绑定事件时,都需要进行检测判断, 但是在同一浏览器中每次检测判断的结果都时一样的,不可能走不同的分支。

惰性模式有两种实现方式:

加载即执行:在文件加载时就对方法进行重新定义,这样在之后的事件注册时就不需要再进行检测判断了,缺点:在页面加载的时候会消耗一定的资源。

var addEvent = function (dom, type, fn) {
    if (document.addEventListener) {
        return function (dom, type, fn) {
            dom.addEventListener(type, fn, false)
        }
    } else if (document.attachEvent) {
        return function (dom, type, fn) {
            dom.attachEvent('on' + type, fn)
        }
    } else {
        return function (dom, type, fn) {
            dom['on' + type] = fn
        }
    }
}()
console.log(addEvent)
// f (dom, type, fn) {
//    dom.addEventListener(type, fn, false)
// }

  在页面加载完后打印addEvent方法,就发现addEvent方法已经和最初定义的不同了,说明addEvent方法在页面加载的过程中就已经被重新定义了。

 

惰性执行:在文件加载的时候不执行,第一次执行函数的时候才在函数内部对函数进行重写,最后再调用重写的方法将方法进行重新定义,优点:加载页面的时候不会执行,不消耗资源。缺点:第一次调用的时候会消耗一定的资源。

var addEvent = function (dom, type, fn) {
    if (dom.addEventListener) {
        addEvent = function (dom, type, fn) {
            dom.addEventListener(type, fn, false)
        }
    } else if (dom.attachEvent) {
        addEvent = function (dom, type, fn) {
            dom.attachEvent('on' + type, fn)
        }
    } else {
        addEvent = function (dom, type, fn) {
            dom['on' + type] = fn
        }
    }
    addEvent(dom, type, fn)
}

let dom1 = document.getElementById('btn')
setTimeout(() => {
    addEvent(dom1, 'click', function () {
        console.log('按钮绑定事件')
    })
    console.log(addEvent)
    // f(dom, type, fn) {
    //     dom,addEventListener(type, fn, false)
    // }
}, 1000)
console.log(addEvent)
// f(dom, type, fn) {
//     if (dom, addEventListener) {
//         addEvent = function (dom, type, fn) {
//             dom.addEventListener(type, fn, false)
//         }
//     } else if (dom.attachEvent) {
//         ad...

  在页面加载后立即打印addEvent方法,输出结果和最初的定义一样,说明在页面加载的过程中并没有对addEvent进行重新定义,延迟1秒后调用addEvent给按钮绑定一个事件,绑定完后打印addEvent发现addEvent已经发生了改变,说明在第一次调用addEvent的时候它被重新定义了。

posted @ 2021-07-19 17:37  leayun  阅读(48)  评论(0编辑  收藏  举报