设计模式
一、设计模式的概念和介绍
1. 什么是设计模式
- 经过大量验证,实验,总结,形成的一套固定的用来解决某类问题的方法
- 是一套经过反复使用、多人知晓的、经过分类的、代码设计经验的总结
2. 有哪些设计模式:
- 构造器模式,模块化模式,暴露模块模式,单例模式,中介者模式,原型模式,命令模式,外观模式,工厂模式,Mixin模式,装饰模式,亨元(Flyweight)模式,MVC模式,MVP模式,MVVM模式,组合模式,适配器模式,外观模式,观察者模式,迭代器模式,惰性初始模式,代理模式,建造者模式
二、具体的设计模式讲解
1. 单例模式
- 单个实例
- 在面向对象方式编程时,经过多次操作,只有一个对象被创建,是单例模式
- 多次new只有一个实例被创建
1.配合闭包实现单例模式: var Fn =(function(){ var obj = {}; return function(n){ obj.name = n; obj.sex = 123; return obj; } })(); var f1 = new Fn("admin"); var f2 = new Fn("root"); console.log(f1 === f2); console.log(Fn); console.log(f1); console.log(f2) 2.配合当前的构造函数,将构造函数自身作为变量使用 function Fn(n){ Fn自身就是一个全局,函数也是变量,函数也可以作为对象使用 if(!Fn._qfobj){ Fn._qfobj = {}; } Fn._qfobj.name = n; return Fn._qfobj; } var f1 = new Fn("admin"); var f2 = new Fn("root"); console.log(f1 === f2); console.log(Fn); console.log(f1); console.log(f2)
2. 组合模式
- 组合对象
- 将多个对象按照一定的规律组合,可以实现批量操作的功能
- 简化了操作,但耗费了更多的性能,递归的思想
- 使用场景
- 组合模式,将对象组合成树状结构
- DOM也是树状结构
//构造独立的对象: //门: class GetHome{ init(address){ console.log(address+ "开门"); } } //电脑: class Computer{ init(address){ console.log(address + "开电脑") } } //空调: class Air{ init(address){ console.log(address + "开空调"); } } //组合器: class Combiner{ constructor(address){ this.address = address; this.arr = []; } add(o){ this.arr.push(o); } init(){ this.arr.forEach(ele =>{ ele.init(this.address); }) } } //测试: //卧室的组合器: var bedroom = new Combiner("卧室"); //2.组合卧室所需的设备: bedroom.add(new Computer); bedroom.add(new Air()); // 3.通过卧室的组合器启动卧室的所有设备: bedroom.init(); //客厅的组合器: var parlour = new Combiner("客厅"); //2.组合客厅的设备: parlour.add(new GetHome()); parlour.add(new Air()); // 3.通过客厅的组合器启动客厅的所有设备: parlour.init(); // 1.整个房子的组合器: var home = new Combiner(); //2.组合客厅和卧室: home.add(bedroom); home.add(parlour); // 3.通过房子的组合器启动客厅和卧室: home.init();
3. 观察者模式
- 发布订阅者模式
- 发布者
- 发布信息
- 订阅者
- 接收信息,根据信息内容作出对应的处理
- 实现广播通信,一个发布者,多个接收者
- 订阅者的耦合非常低,可扩展能力非常强,可以随时加入或离开
- 一对多的关系
class Headmaster{ constructor(){ //准备一个容器,用来存放将来可能发生的行为,状态: this.msg = {}; } on(type,cb){//向容器中添加状态 //判断是否是已存状态 if(this.msg[type]){ this.msg[type].push(cb);//如果是已存状态,只添加处理功能 }else{ this.msg[type] = [cb];//如果是未知状态,设置一个数组,保存处理功能 } } off(type,cb){//用来删除容器中的状态: //删除之前先判断是否存在: if(!this.msg[type]) return; //如果存在,找到这个状态,找到要删除的处理功能: for(var i = 0;i<this.msg[type].length;i++){ if(this.msg[type][i] === cb){ this.msg[type].splice(i,i);//删除 break; } } } emit(type){//用来模拟发布者状态 //处理对应状态之前先判断是否存在: if(!this.msg[type]) return; this.msg[type].forEach(element =>{ element(); }); } } var h = new Headmaster(); //定义学员手册: h.on("抽烟",function(){ console.log("罚款") }); h.on("抽烟",function(){ console.log("罚站"); }); h.on("喝酒",function(){ console.log("叫家长"); }); h.on("烫头",function(){ console.log("剃掉"); }); h.on("烫头", fn); function fn(){ console.log("1"); } console.log(h.msg); //删除其中一项的处理功能(可以删除掉的函数必须为有名函数: h.off("烫头",fn)
4. 拓展
- 策略模式
- 策略:计划,规划
- 提前预置某些状态的处理功能,根据不同的状态决定哪个功能被调用
- 适配器模式
- 适配器,电源适配器:将不符合规范的内容,包装成符合规范的内容
class Phone{ constructor(){ this.name = "手机" } call(){ console.log("可以打电话") } game(){ console.log("可以玩游戏") } song(){ console.log("可以听歌") } } class Pad{ constructor(){ this.name = "平板" } game(){ console.log("可以玩游戏") } song(){ console.log("可以听歌") } } class Mp3{ constructor(){ this.name = "mp3" } song(){ console.log("可以听歌") } book(){ console.log("可以看电子书") } } function test(obj){ if(obj.call){ obj.call(); }else{ console.log(obj.name + "没有打电话功能") } if(obj.game){ obj.game(); }else{ console.log(obj.name + "没有玩游戏功能"); } if(obj.song){ obj.song(); }else{ console.log(obj.name + "没有听歌功能"); } if(obj.book){ obj.book(); }else{ console.log(obj.name + "没有电子书功能"); } } var phone = new Phone; test(phone);
- 代理模式
- 代理,快递员,代替某人完成某事
- 代理系统的内置功能的执行,拦截数据,记录,或另做他用,或加工后使用
- 功能A 调用了 功能B 时,有数据传递
- 记录传递了什么数据
- 将传递的数据做二次使用
- 对传递的数据进行加工
//定义功能A: class ModuleA{ constructor(){ this.name = "功能A" } send(obj,d){ obj.getData(d) } } //定义功能B: class ModuleB{ constructor(){ this.name = "功能B"; } getData(d){ console.log("这是接收到的数据:" + d); } } //定义代理模块: class Agent{ constructor(a,b){ this.a =new a(); this.b = new b(); } send(d){ //截获的数据 this.d = d; this.a.send(this.b,d); } show(){ console.log(this.d); } } var agent = new Agent(ModuleA,ModuleB); agent.send("你好"); agent.show();
- MVC模式
- MVC原本是一种后台语言中的设计模式
- M:module,模块层,管理的是数据
- V:view,视图层,表现,呈现给用户的页面
- C:control,控制器层,逻辑,用来处理逻辑,根据不同的指令,选择不同的数据,在不同的视图中呈现
- 用户,调用控制器中的指令,控制器根据指令去取module层中的数据,暂存;再去view层中取出对应的视图,将数据发给视图,由视图做渲染
//定义控制层的属性和方法: class Control{ constructor(){ this.m = new Module(); this.v = new View(); } task1(){ var d = this. m.data1(); this.v.page2(d); } task2(){ var d = this.m.data3(); this.v.page1(d); } } //定义模块层: class Module{ data1(){ return "hello"; } data2(){ return "world"; } data3(){ return "123"; } } //定义视图层: class View{ page1(d){ console.log(d); } page2(d){ alert(d); } page3(d){ document.write(d); } } var c = new Control(); c.task1(); c.task2();
- 工厂模式:
function Create(n, s, a){ var obj = {}; obj.name = n; obj.sex = s; obj.age = a; return obj; } var o1 = Create("admin","1",17); var o2 = Create("admin","1",17); var o3 = Create("admin","1",17);