单例模式
定义
确保一个类仅有一个实例,并提供一个拜访它的全局拜访点。(屡次实例化类也只创立一个实例对象)
实现
// 单例构造函数
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;
}
})();
// 创立实例对象 1
var a = new Singleton('a');
// 创立实例对象 2
var 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) // 手机库存有余
应用场景
商品促销不同顾客优惠力度不同的购买