JS 的设计模式

什么是设计模式

  • 假设有一个空房间,我们要日复一日地往里 面放一些东西。最简单的办法当然是把这些东西 直接扔进去,但是时间久了,就会发现很难从这 个房子里找到自己想要的东西,要调整某几样东 西的位置也不容易。所以在房间里做一些柜子也 许是个更好的选择,虽然柜子会增加我们的成 本,但它可以在维护阶段为我们带来好处。使用 这些柜子存放东西的规则,或许就是一种模式

目的

  • 学习设计模式, 有助于我们写出可复用和可维护性高的代码
  • 设计模式的原则是 找出程序中变化的地方 并将变化的封装起来

常用的设计模式

1.单例模式 比如 vuex

  • 只能创建单个对象,和工厂模式相对
  • 场景:
    • vuex
  • 实现:
class Singleton {
    constructor (name) {
        this.name = name
        this.instance = null
    }
    getName () {
        alert (this.name)
    }
    static getInstance (name) {
        if (!this.instance) {
            this.instance = new Singleton(name)
        }
        return this.instance
    }
}

const ins = new Singleton('123')
const instance0 = Singleton.getIntance('000)
const instance1 = Singleton.getIntance('123')


2. 策略模式:

  • 提前将可能发生的情况都考虑到位,并给出对应的解决方案
  • 优点:
    • 可以避免 if else 语句 代码结构清晰 更加直观 有利于维护
  • 缺点:
    • 往往策略集会比较多, 我们需要事先了解定义好所有的情况 才能选择一个最优的方法(不算缺点 但是违反了 最少知识原则)
  • 场景:
    • 轮播图中左右按钮的区分
    • 左右移动方向的确定
    • 小标被点击时的方向
const strategies = {aaa ( salary ) {return salary * 4;},bbb ( salary ) {return salary * 3;},ccc ( salary ) {return salary * 2;}
};

3. 代理模式:

  • 为对象提供一个代用品或者占位符, 以便控制对它的访问
  • 当客户不方便直接访问一个 对象或者不满足需要的时候,提供一个替身对象 来控制对这个对象的访问,客户实际上访问的是 替身对象。替身对象对请求做出一些处理之后, 再把请求转交给本体对象
  • 场景:
    • 事件委托
    • 服务器代理
// 主体 发送消息
function sendMsg (msg) {
    console.log(msg)
}

// 代理, 对消息进行过滤
function proxySendMsg (msg) {
    if (typeof msg === 'undefined') {
        console.log('deny')
        return
    }
    // 有消息则进行过滤
    mag = ('' + msg).replace(/泥\s*煤/g, '')
    sendMsg(msg)
}

sendMsg('泥煤呀泥 煤呀'); // 泥煤呀泥 煤呀
proxySendMsg('泥煤呀泥 煤'); // 呀
proxySendMsg(); // deny

在访问主体之前进行控制, 没有消息的时候直接在代理中返回, 拒绝访问主体, 这就是 数据保护代理的模式
有消息的时候对敏感字符进行了处理, 这就是 虚拟代理的模式

  • 虚拟代理的实际应用
    • 在滚动事件触发的时候,也许不需要频繁触发,我们可以引入函数节流,这是一种虚拟代理的实现
// 先定义一个防抖函数
const debounce = (fn, delay = 200) => {
    let timer = null
    return function ()  {
        let arg = arguments
        // 每次操作前 清除上次的定时器
        clearTimeout(timer)
        timer = null
        // 定义新的定时器, 过一段时间后操作
        timer = setTimeout(() => {
            fn(arg) // 这里不使用箭头函数就要处理 this 指向 fn.apply(this,arg)
        }, delay)
    }
}
let count = 0

// 主体
function scrollHandle (e) {
    console.log(e.type, ++count)
}

// proxy
var proxyScrollHandle = (function() {
    return debounce(scrollHandle, 500)
})()

window.onscroll = proxyScrollHandle

4. 工厂模式:

  • 工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型。
  • 简单的说: 假如我们想在网页面里插入一些元素,而这些元素类型不固定,可能是图片、链接、文本,根据工厂模式的定义,在工厂模式下,工厂函数只需接受我们要创建的元素的类型,其他的工厂函数帮我们处理。
// 文本工厂
class Text {
    constructor (text) {
        this.text = text
    }
    insert (where) {
        const txt = docoument.createTextNode(this.text)
        where.appendChild(txt)
    }
}
// 链接工厂
class Link {
    constructor (url) {
        this.url = url
    }
    insert (where) {
        const link = documnet.createElement('a')
        link.href = this.url
        link.appendChild(document.createTextNode(this.url))
        where.appendChild(link)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值