JavaScript中的设计模式
设计模式,是针对特定问题,给出简洁而优雅的解决方案。
Javascript中常见的设计模式有很多种:
1.单例模式
2.策略模式
3.代理模式
4.迭代器模式
5.发布-订阅模式
6.命令模式
7.组合模式
8.模板方法模式
9.享元模式
10.职责链模式
11.中介者模式
12.装饰者模式
13.状态模式
14.适配者模式
在初学JavaScript时,先介绍三种设计常见的设计模式:
单例模式
也就是,使用一个构造函数生成的实例化对象。因为在平常的初始化构造函数时,几班是属性方法都完全相同,默认也是生成两个不同的构造函数,如此操作就会占用很多的的内存空间,降低了执行效率。
而单例模式所解决的问题就是:在同一个构造函数,能够生成同一个实例化对象。
单例模式原理:
判断这个构造函数是否使用过,如果使用过,返回之前的对象。如果没有使用过,就执行构造函数生成实例化对象。
代码实现:
//1.创建一个构造函数,空的
function CreatObj(){}
//2.创建一个变量,原始数值可有可无(基本类型)
let res=null;
//3.创建单例模式函数
function Singleton(){
// 如果res中存储值为null,也就证明没执行过构造函数,可以第一次执行构造函数,将构造函数执行结果存入res
if(res==null){
res=new CreatObj();
}
// 存入构造函数的执行结果,也就是实例化对象
// 最终返回结果是我们创建的变量
return res;
}
//4.通过单例模式函数来生成实例化对象
const obj1=Singleton();
const obj2=Singleton();
console.log(obj1==obj2)
结果:
组合模式
组合模式,通俗的讲就是通过一个‘遥控器’,来控制所有入口函数的执行。也就是我们能够用相同的方式去处理一个甚至多个对象。
代码实现:
先写三个构造函数,包含多个多个方法,而init()入口函数控制了构造函数中所有方法的执行。
class A{
constructor(){}
// 入口函数
init(){
this.a1();
this.a2();
this.a3();
this.a4();
}
// 构造函数方法
a1(){console.log('我是a1')}
a2(){console.log('我是a2')}
a3(){console.log('我是a3')}
a4(){console.log('我是a4')}
}
class B{
constructor(){}
// 入口函数
init(){
this.b1();
this.b2();
}
// 构造函数方法
b1(){console.log('我是b1')}
b2(){console.log('我是b2')}
}
class C{
constructor(){}
// 入口函数
init(){
this.c1();
}
// 构造函数方法
c1(){console.log('我是c1')}
}
组合模式
class Compose{
constructor(){
this.arr=[];
}
add(obj){
this.arr.push(obj)
}
execute(){
this.arr.forEach(function(item){
item.init();
})
}
}
const comp=new Compose();
comp.add(new A());
comp.add(new B());
comp.add(new C());
comp.execute();
在组合模式的构造函数中,通过add()这个方法,将所有需要执行的构造函数的实例化对象加进数组,并在execute()方法中,循环遍历得到每一个实例化对象,并且调用其中的入口函数,从而执行所有的方法。
结果:
发布-订阅模式
发布-订阅模式,又被称作为,观察者模式。
官方定义
的那个一个对象的状态发生改变时,所有依赖于这个对象的相关的对象,都要发送通知,并且根据程序的需求,主动更新数据。
作用
主要是解决主体与相关对象的功能的耦合,也就是主体对象的状态改变,相关个体,数据更新。
核心代码
需要一个观察者,抽象定义为一个对象{}
需要有个属性,也称消息盒子(要执行所有的事件)
需要一个on方法,向消息盒子中添加事件
需要一个emit方法,用于发布事件
需要一个off方法,删除已经添加的方法
观察者模式的构造函数
观察者模式——定义on方法
// on方法
// 将需要执行的事件,写入on方法
// 参数一:需要执行的事件类型
// 参数二:需要执行的事件的内容
on(type,fun){//需要执行的操作是函数
// 将执行类型与事件写入message消息盒子中
// 写入之前要判断,是否有重复的内容写入
if(!this.message[type]){
//消息盒子中没有这个属性,就进行创建
this.message[type]=[fun];
}else{
// 消息盒子中,存在这个属性,就将这个内容放进去即可
// 向事件类型中写入需要执行的内容
this.message[type].push(fun)
}
}
观察者模式——定义emit方法
// emit 执行,可能是全部执行,也可能只执行一个
// 参数一:需要执行的类型
// 参数二:需要执行的内容(是不确定的)
// 所以使用 合并运算符 ...形参
emit(type,...arr){
if(!this.message[type]){
// 先判断这个类型,是否存在,不存在直接return
return;
}else{
// 类型存在,执行内容
// 通过双层循环,遍历两个数组,如果里面有相同的就执行这个方法
// 第一个数组 arr 第二个数组this.message[type]
for(var i=0;i<arr.length;i++){
for(var j=0;j<this.message[type].length;j++){
if(arr[i]===this.message[type][j]){
arr[i]();
}
}
}
}
}
观察者模式——定义off方法
// off执行,删除这个消息盒子中,这个类型的,符合所有执行内容
off(type,fun){
if(!this.message[type]){
// 先判断有没有这个类型,要是没有,就执行return,终止之后函数的执行
return;
}else{
// 有这个类型,就删除相应的类型
// 类型以数组存储,那么循环遍历数组,删除与之相同的
for(let i=0;i<this.message[type].length;i++){
if(fun===this.message[type][i]){
this.message[type].splice(i,1);
// 为了防止塌陷的操作
i--;
}
}
}
}
观察者模式的添加(on)与执行(emit)
// 通过构造函数,生成实例化对象
const obj=new Observer();
function baba(){
console.log('请老爸,下午2点到学校')
}
function mama(){
console.log('请老妈,上午10点到学校')
}
function yeye(){
console.log('请爷爷,下午3点到学校')
}
function jiancha1(){
console.log('写给老师的检查')
}
function jiancha2(){
console.log('写给主任的检查')
}
function jiancha3(){
console.log('写给校长的检查')
}
obj.on('call',baba);
obj.on('call',mama);
obj.on('call',yeye);
obj.emit('call',baba,mama,yeye);
结果:
在上面执行代码的基础上,进行off方法的执行
obj.on('call',baba);
obj.on('call',mama);
obj.on('call',yeye);
// obj.emit('call',baba,mama,yeye);
obj.off('call',yeye);
obj.off('call',mama);
obj.emit('call',baba,mama,yeye)
结果: