单例模式

定义

确保一个类仅有一个实例,并提供一个拜访它的全局拜访点。(屡次实例化类也只创立一个实例对象)

实现

// 单例构造函数function CreateSingleton (name) {    this.name = name;    this.getName();};// 获取实例的名字CreateSingleton.prototype.getName = function() {    console.log(this.name)};// 单例对象var Singleton = (function(){    var instance;    return function (name) {        if(!instance) {            instance = new CreateSingleton(name);        }        return instance;    }})();// 创立实例对象1var a = new Singleton('a');// 创立实例对象2var b = new Singleton('b');console.log(a===b);

场景

模态框

策略模式

定义

一些列算法,把他们封装起来,并且能够互相替换。(就是把看似毫无分割的代码提取封装、复用,使之更容易被了解和拓展)

实现

1.定义方法(表单校验的办法)

    const strategies = {      // 非空      noEmpty: function(value, errMsg){        if(value === ''){          return errMsg        }      },      // 最小长度      minLength: function(value, length, errMsg){        if(!value || value.length < length){          return errMsg        }      },      // 最大长度      maxLength: function(value, length, errMsg){        if(value.length > length){          return errMsg        }      }    }

2.设置校验器

    // 创立验证器    var Validator = function(strategies){      this.strategies = strategies      this.cache = [] // 存储校验规定    }    // 增加校验规定    Validator.prototype.add = function(dom, rules){      rules.forEach(item => {        this.cache.push(() => {          let value = dom.value          let arr = item.rule.split(':')          let name = arr.shift()          let params = [value, ...arr, item.errMsg]          // apply保障上下文统一          return this.strategies[name].apply(dom, params)        })      })    }    // 校验后果    Validator.prototype.validate = function(dom, rules, errMsg){      // 遍历cache外面的校验函数      for(let i = 0, validateFun; validateFun = this.cache[i++];){        const message = validateFun()        // 返回报错信息,终止验证并抛出异样        if(message) return message      }    }

3.进行校验

 // 校验函数    function validate(){      // 实例验证器      const validator = new Validator(strategies)      // 增加验证规定      validator.add(form.username, [        {          rule: 'noEmpty',          errMsg: '用户名不能为空!'        },        {          rule: 'minLength:3',          errMsg: '用户名长度大于3!'        }      ])      validator.add(form.password, [        {          rule: 'minLength:6',          errMsg: '明码长度大于6!'        },        {          rule: 'maxLength:10',          errMsg: '明码最大长度为10!'        }      ])      // 进行校验,并返回后果      return validator.validate()    }

应用场景

表单校验,多层if-else,switch判断

代理模式

定义

为其余对象提供一种代理以管制对这个对象的拜访(拦挡,中间层,防止间接批改原对象)

缓存代理实现

const getCacheProxy = (fn, cache = new Map()) => {  return new Proxy(fn, {    apply(target, context, args) {      const argsString = args.join(' ');      if (cache.has(argsString)) {        // 如果有缓存,间接返回缓存数据        console.log(`输入${args}的缓存后果: ${cache.get(argsString)}`);                return cache.get(argsString);      }      const result = fn(...args);      cache.set(argsString, result);      return result;    }  })}

调用

const getFibProxy = getCacheProxy(getFib);getFibProxy(40);

场景

设置公有属性,网络拜访须要设置拦挡时,缓存等。

公布订阅

定义

一种对象间一对多的依赖关系,当一个对象的状态发送扭转时,所有依赖于它的对象都将失去状态扭转的告诉。(一对多)

实现思路

  • 在该对象上创立一个缓存列表(调度核心Event Channel)
  • on办法用来把函数增加到缓存列表中(订阅者注册事件到调度核心)
  • emit办法取到argument里第一个当作event,依据event值去执行对应缓存列表中的函数(发布者公布事件到调度核心,调度核心解决代码)
  • off办法能够依据event值勾销订阅(勾销订阅)
  • once办法只监听一次,调用结束后删除缓存函数(订阅一次)

代码实现

class EventEmitter {    constructor() {        // 缓存列表        this.listener = {}    }    // 订阅    on(eventName, fn) {        // 如果对象中没有对应的 event 值,也就是说明没有订阅过,就给 event 创立个缓存列表        // 如有对象中有相应的 event 值,把 fn 增加到对应 event 的缓存列表里        if(!this.listener[eventName]){            this.listener[eventName] = [];        }        this.listener[eventName].push(fn);    }    // 勾销订阅    off(eventName, fn) {        let callbacks = this.listener[eventName];        // 缓存列表中没有对应的fn,返回false        if(!callbacks){            return false;        }        if(!fn){            // 如果未传入fn,则将缓存列表中对应的fn都清空            callbacks && (callbacks.length = 0);        } else {            let cb;            // 遍历所对应的fn,判断和那个fn雷同,雷同则删除            for (let i = 0, cbLen = callbacks.length; i < cbLen; i++) {                cb = callbacks[i];                if (cb == fn || cb.fn == fn) {                    callbacks.splice(i, 1);                    break                }            }        }    }    // 监听一次    once(eventName, fn) {        // 先绑定,运行时删除对应的值        let on = () => {            this.off(eventName, on);            fn.apply(this, arguments);        }        on.fn = fn;        this.on(eventName, on);    }    // 公布    emit(eventName, data) {        const callbacks = this.listener[eventName];        if(callbacks) {            callbacks.forEach((c) => {                c(data);            })        }    }}let a = new EventEmitter();function aa(x) {    console.log(x);}a.on("kak", aa)a.on("kak", (data) => {    console.log("1", data);})a.emit('kak', 'hahahah');a.off('kak',aa);a.emit('kak', 'hahahah');

场景

权限状态,一对多的场景。

中介者模式

定义

用一个中介对象来封装一系列的对象交互。中介者使各对象不须要显式地互相援用,从而使其耦合涣散,而且能够独立地扭转它们之间的交互。(是对象与对象之间)

实现

  // 创立中介者  var Mediator = function() {    var _msg = {}    return {      register: function(type, action) {        if (!_msg[type]) _msg[type] = []        _msg[type].push(action)      },      send: function(type) {        if(_msg[type]) {          for (var i = 0; i < _msg[type].length; i++) {            _msg[type][i] && _msg[type][i]()          }        }      }    }  }()  Mediator.register('demo', function () {    console.log('first')  })  Mediator.register('demo', function () {    console.log('second')  })  Mediator.send('demo')

场景

商品抉择不同色彩,尺码(等不同维度)时显示库存

组合模式

定义

又叫 “局部整体” 模式,将对象组合成树形构造,以示意 “局部-整体” 的层次结构。通过对象的多态性体现,使得用户对单个对象和组合对象的应用具备一致性。(文件拜访目录,tree构造)。对外裸露对立接口,拜访顶层对象时会自上而下遍历子对象。

实现

// 树对象 - 文件目录class CFolder {    constructor(name) {        this.name = name;        this.files = [];    }    add(file) {        this.files.push(file);    }    scan() {        for (let file of this.files) {            file.scan();        }    }}// 叶对象 - 文件class CFile {    constructor(name) {        this.name = name;    }    add(file) {        throw new Error('文件上面不能再增加文件');    }    scan() {        console.log(`开始扫描文件:${this.name}`);    }}let mediaFolder = new CFolder('娱乐');let movieFolder = new CFolder('电影');let musicFolder = new CFolder('音乐');let file1 = new CFile('钢铁侠.mp4');let file2 = new CFile('再谈记忆.mp3');movieFolder.add(file1);musicFolder.add(file2);mediaFolder.add(movieFolder);mediaFolder.add(musicFolder);mediaFolder.scan();/* 输入:开始扫描文件:钢铁侠.mp4开始扫描文件:再谈记忆.mp3*/

场景

树形构造查找(地区级联显示

责任链模式

定义

使多个对象都有机会解决申请,从而防止了申请的发送者与多个接收者间接的耦合关系,将这些接收者连接成一条链,顺着这条链传递该申请,直到找到能解决该申请的对象。

实现

function order500 (orderType, pay, stock) {  if (orderType === 1 && pay === true) {    console.log('500元定金预购,失去100元优惠券')  } else {    return 'nextSuccessor'  }}function order200 (orderType, pay, stock) {  if (orderType === 2 && pay === true) {    console.log('200元定金预购,失去50元优惠券')  } else {    return 'nextSuccessor'  }}function orderNormal (orderType, pay, stock) {  if (stock > 0) {    console.log('普通用户购买,无优惠券')  } else {    console.log('手机库存有余')  }}

应用AOP创立职责链

Function.prototype.after = function (fn) {  const self = this  return function () {    const res = self.apply(this, arguments)    if (res === 'nextSuccessor') {      return fn.apply(this, arguments)    }    return res  }}const order = order500.after(order200).after(orderNormal)order(1, true, 500)   // 500元定金预购,失去100元优惠券order(2, true, 500)   // 200元定金预购,失去50元优惠券order(3, true, 500)   // 普通用户购买,无优惠券order(1, false, 0)    // 手机库存有余

应用场景

商品促销不同顾客优惠力度不同的购买