二十、设计模式
所谓的设计模式,就是为了解决特定的问题,进而定义的程序的一种书写方式
目的:就是为了优化代码,减少冗余
一、工厂模式
将重复冗余的定义对象属性和方法的程序封装在一个函数内,调用函数就可以完成对对象的定义
定义一个函数,生成一个对象,添加上方法、属性、再返回这个对象
1 function createObj(name,sex,age,addr,hobby){ 2 const obj = {}; 3 obj.name = name; 4 obj.age = age; 5 obj.sex = sex; 6 obj.addr = addr; 7 obj.hobby = hobby; 8 obj.fun1 = function(){}; 9 obj.fun2 = function(){}; 10 return obj; 11 }
二、单例模式
单例模式:让通过相同的构造函数,生成的实例化对象,不再被重复定义,不再占用多余的内存地址
1 class SetObj{ 2 constructor(name,age){ 3 this.name = name; 4 this.age = age; 5 } 6 fun1(){} 7 fun2(){} 8 } 9 10 const obj1 = new SetObj('张三',18); 11 const obj2 = new SetObj('李四',20); 12 13 // 同一个构造函数,生成实例化对象 14 // 因为是多次定义新的对象,占用新的内存空间,生成新的内存地址 15 // 因此两个对象是不同的内存地址,是不等关系 16 console.log(obj1 === obj2); // false
-
定义一个构造函数,定义一个变量
-
如果变量没有内容,或者内容是空,证明没有执行过构造函数,没有生成实例化对象,可以执行构造函数
-
1 class CreateObj{}; 2 3 // 定义变量 4 let obj = null; 5 6 function isObj(){ 7 if(obj === null){ 8 obj = new CreateObj(); 9 } 10 return obj; 11 } 12 13 // 使用函数,调用构造函数,创建实例化对象 14 const obj1 = isObj(); 15 const obj2 = isObj(); 16 17 // obj1和obj2中,实际上都存储的是,实例化对象的内存地址,是相等的 18 console.log(obj1 === obj2); // true
三、组合模式
组合模式:使用一个"遥控器"统一启动关闭所有实例化对象的入口函数
1 class Fun1 { 2 constructor() { } 3 init() { 4 this.f1(); 5 this.f2(); 6 } 7 f1() { 8 console.log('1111') 9 } 10 f2() { 11 console.log('2222') 12 } 13 } 14 15 class Fun2 { 16 constructor() { } 17 init() { 18 this.f1(); 19 this.f2(); 20 } 21 f1() { 22 console.log('1111') 23 } 24 f2() { 25 console.log('2222') 26 } 27 } 28 29 // 定义实例化对象 30 const obj1 = new Fun1(); 31 const obj2 = new Fun2(); 32 33 // 每一个构造函数的入口函数,都必须叫 init 34 // 定义一个组合模式的构造函数 35 class Group { 36 constructor() { 37 // 在构造器中定义一个空数组,数组中准备存储所有的入口函数 38 this.arr = []; 39 } 40 41 // 定义一个方法,添加所有的入口函数到数组中 42 // 入口函数,是存储在实例化对象中,将实例化对象添加到数组中 43 // 等于数组中存储对象,对象中包含入口函数 44 add(object) { 45 this.arr.push(object); 46 } 47 48 // 调用数组arr中,存储的实例化对象中的入口函数 49 execute() { 50 // 将数组中存储的实例化对象的入口函数都调用 51 // item就是arr中存储的实例化对象 52 this.arr.forEach((item) => { 53 // 调用每一个实例化对象的入口函数 54 item.init(); 55 }) 56 } 57 } 58 59 // 通过构造函数,生成组合模式的实例化对象 60 const group = new Group(); 61 62 // 向组合模式添加需要执行init()实例化对象 63 group.add(obj1); 64 group.add(obj2); 65 66 // 通过单例模式,一次启动所有添加的实例化对象的入口函数 67 group.execute();
四、观察者模式
-
-
监听某个主体对象,如果主体对象的状态发生改变,记录状态的改变
-
给相关连的其他个体,执行相关的数据更新操作
-
-
观察者模式的核心代码
-
需要一个观察者(一个对象)
-
观察者需要一个属性,存储记录所有的需要执行的程序(消息盒子)
-
on方法,向消息盒子添加需要执行的函数方法
-
emit方法,发布执行消息盒子中定义的函数方法
-
-
1 class CreateObj{ 2 constructor(){ 3 this.msg = []; // 消息盒子,存储要执行的函数方法 4 } 5 6 on(){} // 向消息盒子添加要执行的函数方法 7 emit(){} // 执行消息盒子中函数方法 8 off(){} // 删除消息盒子中函数方法 9 }
1、on方法
向 this.msg 这个消息盒子中,添加需要执行的程序内容
-
-
类型不存在,新增type单元的类型
-
类型存在,在已有的类型方法中,新增方法
-
-
on方法 需要两个参数
-
参数一:新增函数方法类型
-
-
1 class CreateObj { 2 constructor() { 3 this.msg = {}; 4 } 5 // type:方法的类型 6 // fun :添加的函数方法 7 on(type, fun) { 8 // 判断是否有这个类型,没有类型,调用结果是 undefined 9 if (this.msg[type] === undefined) { 10 // 调用结果是undefined,证明没有这个类型 11 // 直接添加类型和方法 12 // type中以数组的形式,存储多个需要执行的函数方法 13 this.msg[type] = [fun]; 14 } else { 15 // 调用结果不是undefined,证明有这个类型 16 // 向这个类型中,新增新的方法 17 this.msg[type].push(fun); 18 } 19 } 20 emit() { } 21 off() { } 22 } 23 const obj = new CreateObj(); 24 25 // 添加方法 26 obj.on('moshou', moshou1); 27 obj.on('moshou', moshou2); 28 29 function moshou1() { 30 console.log('没收手机') 31 } 32 function moshou2() { 33 console.log('没收零食') 34 }
2、off方法
从 this.msg 消息盒子中,删除方法
-
-
如果存在,再执行
-
如果不存在,不执行程序
-
-
判断 执行的 函数方法,是否存在
-
判断存储的函数名称和传参要执行的函数名称是否相同
-
-
需要两个参数
-
参数一:事件类型
-
-
1 class CreateObj { 2 constructor() { 3 this.msg = {}; 4 } 5 // type:方法的类型 6 // fun :添加的函数方法 7 on(type, fun) { 8 // 判断是否有这个类型,没有类型,调用结果是 undefined 9 if (this.msg[type] === undefined) { 10 // 调用结果是undefined,证明没有这个类型 11 // 直接添加类型和方法 12 // type中以数组的形式,存储多个需要执行的函数方法 13 this.msg[type] = [fun]; 14 } else { 15 // 调用结果不是undefined,证明有这个类型 16 // 向这个类型中,新增新的方法 17 this.msg[type].push(fun); 18 } 19 } 20 off(type, fun) { 21 if (this.msg[type] === undefined) { 22 // 证明事件类型不存在,终止程序执行 23 return; 24 } 25 26 // item 是类型中存储的函数名称 27 this.msg[type].forEach((item, key) => { 28 // 存储的函数名称和输入的函数名称相同 29 if (item === fun) { 30 // 执行数组删除单元操作 31 // 从当前索引开始,删除一个单元 32 this.msg[type].splice(key, 1); 33 } 34 }) 35 } 36 emit() { } 37 } 38 const obj = new CreateObj(); 39 40 // 添加方法 41 obj.on('moshou', moshou1); 42 obj.on('moshou', moshou2); 43 44 // 删除方法 45 obj.off('moshou', moshou2); 46 47 function moshou1() { 48 console.log('没收手机') 49 } 50 function moshou2() { 51 console.log('没收零食') 52 }
3、emit方法
将 msg 消息盒子中的方法,都执行
-
参数一:执行的事件类型
-
1 class CreateObj { 2 constructor() { 3 this.msg = {}; 4 } 5 // type:方法的类型 6 // fun :添加的函数方法 7 on(type, fun) { 8 // 判断是否有这个类型,没有类型,调用结果是 undefined 9 if (this.msg[type] === undefined) { 10 // 调用结果是undefined,证明没有这个类型 11 // 直接添加类型和方法 12 // type中以数组的形式,存储多个需要执行的函数方法 13 this.msg[type] = [fun]; 14 } else { 15 // 调用结果不是undefined,证明有这个类型 16 // 向这个类型中,新增新的方法 17 this.msg[type].push(fun); 18 } 19 } 20 off(type, fun) { 21 if (this.msg[type] === undefined) { 22 // 证明事件类型不存在,终止程序执行 23 return; 24 } 25 26 // item 是类型中存储的函数名称 27 this.msg[type].forEach((item, key) => { 28 // 存储的函数名称和输入的函数名称相同 29 if (item === fun) { 30 // 执行数组删除单元操作 31 // 从当前索引开始,删除一个单元 32 this.msg[type].splice(key, 1); 33 } 34 }) 35 } 36 // 通过合并运算符,将需要执行的函数名称,以数组的形式存储 37 emit(type, ...funArr) { 38 // 1,判断类型是否存在,不存在直接终止 39 if (this.msg[type] === undefined) { 40 return; 41 } 42 43 // 2,如果类型存在,比对函数名称,是否存在,如果存在,再执行调用 44 // item是存储的函数名称 45 this.msg[type].forEach((item) => { 46 // funName是输入的函数名称 47 funArr.forEach((funName) => { 48 // 如果这两个函数名称一致,就可以调用函数 49 if (item === funName) { 50 item(); 51 } 52 }) 53 }) 54 } 55 } 56 const obj = new CreateObj(); 57 58 // 添加方法 59 obj.on('moshou', moshou1); 60 obj.on('moshou', moshou2); 61 62 // 删除方法 63 obj.off('moshou', moshou2); 64 65 function moshou1() { 66 console.log('没收手机') 67 } 68 function moshou2() { 69 console.log('没收零食') 70 }