目录
原则
创建型
单例模式
工厂模式
js闭包:函数工厂
结构型
代理模式
装饰器模式
行为型
职责链模式
观察者模式
//checkType('165226226326','mobile')
//result:false
let checkType=function(str, type) {
switch (type) {
case 'email':
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str)
case 'mobile':
return /^1[3|4|5|7|8][0-9]{9}$/.test(str);
case 'tel':
return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
default:
return true;
}
}
想添加其他规则就得在函数里面增加 case 。违反了开放-封闭原则(对扩展开放,对修改关闭)
给 API 增加一个扩展的接口:
let checkType=(function(){
let rules={
email(str){
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
},
mobile(str){
return /^1[3|4|5|7|8][0-9]{9}$/.test(str);
}
};
//暴露接口
return {
//校验
check(str, type){
return rules[type]?rules[type](str):false;
},
//添加规则
addRule(type,fn){
rules[type]=fn;
}
}
})();
//调用方式
//使用mobile校验规则
console.log(checkType.check('188170239','mobile'));
//添加金额校验规则
checkType.addRule('money',function (str) {
return /^[0-9]+(.[0-9]{2})?$/.test(str)
});
//使用金额校验规则
console.log(checkType.check('18.36','money'));
一个类只有一个实例,并提供一个访问它的全局访问点。
class LoginForm {
constructor() {
this.state = 'hide'
}
show() {
if (this.state === 'show') {
alert('已经显示')
return
}
this.state = 'show'
console.log('登录框显示成功')
}
hide() {
if (this.state === 'hide') {
alert('已经隐藏')
return
}
this.state = 'hide'
console.log('登录框隐藏成功')
}
}
LoginForm.getInstance = (function () {
let instance
return function () {
if (!instance) {
instance = new LoginForm()
}
return instance
}
})()
let obj1 = LoginForm.getInstance()
obj1.show()
let obj2 = LoginForm.getInstance()
obj2.hide()
console.log(obj1 === obj2)
优点:
缺点:
应用:登录框
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。
该模式使一个类的实例化延迟到了子类。
而子类可以重写接口方法以便创建的时候指定自己的对象类型。
class Product1 {
product() {
console.log("生产一线");
}
}
class Product2 {
product() {
console.log("生产二线");
}
}
class Factory {
constructor() {
this.Product1 = Product1;
this.Product2 = Product2;
}
create(name, callBack) {
const product = new this[name]();
product.product();
return callBack("susess");
}
}
let p = new Factory();
p.create("Product1", (res) => {
console.log(res);
});
不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中
class Car {
constructor(name, color) {
this.name = name;
this.color = color;
}
}
class Factory {
static create(type) {
switch (type) {
case "car":
return new Car("汽车", "白色");
break;
case "bicycle":
return new Car("自行车", "黑色");
break;
default:
console.log("没有该类型");
}
}
}
let p1 = Factory.create("car");
let p2 = Factory.create("bicycle");
console.log(p1, p1 instanceof Car); // {name: '汽车', color: '白色'} true
console.log(p2, p2 instanceof Car); // {name: '自行车', color: '黑色'} true
function makeAdder(x) {
return function (y) {
return x + y;
};
}
var add5 = makeAdder(5);// fun(y){5+y}
var add10 = makeAdder(10);// fun(y){10+y}
console.log(add5(2)); // 7
console.log(add10(2)); // 12
优点:
缺点:添加新产品时,需要编写新的具体产品类,一定程度上增加了系统的复杂度
是为一个对象提供一个代用品或占位符,以便控制对它的访问
应用:
1. 给"ul"标签添加点击事件
2. 当点击某"li"标签时,该标签内容拼接"."符号。如:某"li"标签被点击时,该标签内容为".."
注意:
1. 必须使用DOM0级标准事件(onclick)
target表示当前触发事件的元素
currentTarget是绑定处理函数的元素
只有当事件处理函数绑定在自身的时候,target才会和currentTarget一样
- .
- .
- .
动态地给某个对象添加一些额外的职责,是一种实现继承的替代方案
class Cellphone {
create() {
console.log('生成一个手机')
}
}
class Decorator {
constructor(cellphone) {
this.cellphone = cellphone
}
create() {
this.cellphone.create()
this.createShell(cellphone)
}
createShell() {
console.log('生成手机壳')
}
}
// 测试代码
let cellphone = new Cellphone()
cellphone.create()
console.log('------------')
let dec = new Decorator(cellphone)
dec.create()
优点:
缺点:
应用:
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
// 请假审批,需要组长审批、经理审批、总监审批
class Action {
constructor(name) {
this.name = name
this.nextAction = null
}
setNextAction(action) {
this.nextAction = action
}
handle() {
console.log( `${this.name} 审批`)
if (this.nextAction != null) {
this.nextAction.handle()
}
}
}
let a1 = new Action("组长")
let a2 = new Action("经理")
let a3 = new Action("总监")
a1.setNextAction(a2)
a2.setNextAction(a3)
a1.handle()
优点:
缺点:
应用:
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result')
},
1000);
})
p1.then(res => console.log(res), err => console.log(err))
分析Promise的调用流程:
Promise
的构造方法接收一个executor()
,在new Promise()
时就立刻执行这个executor回调executor()
内部的异步任务被放入宏/微任务队列,等待执行then()
被执行,收集成功/失败回调,放入成功/失败队列executor()
的异步任务被执行,触发resolve/reject
,从成功/失败队列中取出回调依次执行观察者模式:收集依赖 -> 触发通知 -> 取出依赖执行
在Promise里,执行顺序是then收集依赖 -> 异步触发resolve -> resolve执行依赖
。
class MyPromise {
// 构造方法接收一个回调
constructor(executor) {
this._resolveQueue = [] // then收集的执行成功的回调队列
this._rejectQueue = [] // then收集的执行失败的回调队列
/*由于resolve/reject是在executor内部被调用,
因此需要使用箭头函数固定this指向, 否则找不到this._resolveQueue*/
let _resolve = (val) => {
// 从成功队列里取出回调依次执行
while(this._resolveQueue.length) {
const callback = this._resolveQueue.shift()
callback(val)
}
}
// 实现同resolve
let _reject = (val) => {
while(this._rejectQueue.length) {
const callback = this._rejectQueue.shift()
callback(val)
}
}
// new Promise()时立即执行executor,并传入resolve和reject
executor(_resolve, _reject)
}
// then方法,接收一个成功的回调和一个失败的回调,并push进对应队列
then(resolveFn, rejectFn) {
this._resolveQueue.push(resolveFn)
this._rejectQueue.push(rejectFn)
}
}