二十、设计模式

所谓的设计模式,就是为了解决特定的问题,进而定义的程序的一种书写方式

目的:就是为了优化代码,减少冗余

一、工厂模式

将重复冗余的定义对象属性和方法的程序封装在一个函数内,调用函数就可以完成对对象的定义

定义一个函数,生成一个对象,添加上方法、属性、再返回这个对象

 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方法,发布执行消息盒子中定义的函数方法

    • off方法,删除消息盒子中添加的方法

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 消息盒子中,删除方法

  • 判断执行的类型是否存在(看结果是否是undefined)

    • 如果存在,再执行

    • 如果不存在,不执行程序

  • 判断 执行的 函数方法,是否存在

    • 判断存储的函数名称和传参要执行的函数名称是否相同

  • 需要两个参数

    • 参数一:事件类型

    • 参数二:需要执行的函数名称

 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 }

 

posted @ 2021-07-18 14:41  大米饭盖饭  阅读(33)  评论(0)    收藏  举报