概述:
设计模式是一种固定的解决某个问题的一种方式,不区分语言,常用的设计模式有23种,分为三大类(针对类和对象)
设计模式分类
创建型 (创建对象)单例模式、工厂模式
结构型(将多个小结构变成一个大结构)组合模式 代理模式 装饰器模式 适配器模式
行为型(对应类和对象的行为进行相关处理)观察者模式
设计模式的原则
开闭原则
里氏置换原则
单一原则
依赖倒置原则
接口隔离原则
迪米特原则
工厂模式
根据工厂方法生成对象
function factory(name){ //手动构建对象 var obj = new Object() //给对象进行属性赋值 obj.name = name //手动返回对象 return obj } //调用工厂生产对象 let obj1 = factory('jack') let obj2 = factory('tom')
单例模式
//基础类 class Instance{ constructor(){ } } //闭包实现 function closureSingleton(){ var instance=null return function(){ if(!instance){ instance=new Instance() } return instance } } let single=closureSingleton() let instance1=new single() let instance2=new single() console.log(instance1==instance2); //原型 function prototypeSingleton(){ if(!prototypeSingleton.prototype.instance){ prototypeSingleton.prototype.instance=new Person() } return prototypeSingleton.prototype.instance } let instance3=new single() let instance4=new single() console.log(instance3==instance4); //静态属性 function staticSingleton() { if(!staticSingleton.instance){ staticSingleton.instance=new Person() } return staticSingleton.instance } let instance5=new single() let instance6=new single() console.log(instance5==instance6); //全局属性实现 function globalSingleton() { if(!window.instance){ window.instance=new Person() } return window.instance } let instance7=new single() let instance8=new single() console.log(instance7==instance8);
组合模式(*)
将多个对象的相同方法或者属性组合到一块
class GOToHome { constructor() { this.action = () => { console.log('回家'); } } } class OpenComputer { constructor() { this.action = () => { console.log('打开电脑'); } } } class PlayGame { constructor() { this.action = () => { console.log('玩游戏'); } } } //将多个方法组合在一起进行调用 class Combiner { constructor() { this.list = [] } push(obj) { this.list.push(obj) } excute(fnName, ...arg) { this.list.forEach(item => { item[fnName].call(this, ...arg) }) } } let combiner = new Combiner() combiner.push(new GOToHome()) combiner.push(new OpenComputer()) combiner.push(new PlayGame()) combiner.excute('action')
组合模式在vue中的使用
Vue.use(自动执行install)
install
如果在use里面传入的是一个函数 那么他会把这个函数直接当成install 如果传的是对象 他会自动
去找里面的instal方法
模拟实现use和install
class Vue { constructor() { this.fnList = [] } use(obj) { //如果他是一个函数 那么这个函数直接当成install if (typeof obj == 'function') { this.fnList.push(obj) } //如果他是对象就找里面的install if (typeof obj == 'object') { this.fnList.push(obj.install) } //调用执行 this.execute() } execute() { //遍历对应的函数列表 this.fnList.forEach((fn) => { fn() }) } } var vue = new Vue() vue.use({ install() { console.log('你好') } }) vue.use({ install() { console.log('世界') } }) vue.use(() => { console.log('哈哈哈哈') })
装饰器模式
概述;就是在不影响原本类的基础上,进行功能扩展,又称为包装模式
代码实现
<script> //基础类 class Car{ constructor(){ } run(){ console.log('跑'); } } //包装类 class Decorator{ constructor(car){ this.car=car } fly(){ console.log('飞'); this.car.run() } } new Decorator(new Car()).fly() </script>
在typeScript中有个对应的装饰器修饰 @Decorator
观察者模式 (*)
概述:是前端最常用的模式,又被称为发布者-订阅者模式。核心是一个对应的发布者进行发布,以及对应的有个订阅者(对于发布的内容进行监听),发布者将对应的内容发布,订阅者就会收到信息从而进行对应的处理
观察者模式的核心内容
发布者
订阅者
相关处理
事件也是一个观察者模式
element.addEventListener('事件名',处理函数) element.removeEventListener('事件名',处理函数)
简单的事件示例
<button>点我</button> <script> let btn = document.querySelector('button') btn.addEventListener('click',handler) function handler(){ console.log('点击了') } </script>
发布者button
订阅者JavaScript
处理 handler
分析这个事件的相关内容
发布者
事件名
处理函数
相关关系
事件名和处理函数的关系 一对多 (一个事件可以有多个处理函数)click:[handler1,handler2]
发布者和事件名的关系
一对多 (一个发布者可以发布多个事件) {事件名:[处理函数]}
根据对应的事件监听机制来模拟观察者
事件监听的过程
事件发布 (有对应的事件名)on
事件执行 (根据对应的事件名执行相关的处理函数) emit
事件取消
(将对应的事件移除)off
代码构建
class ObServer{ constructor(){ //{click:[handler1,handler2],mousemove:[handler1,handler2]} this.obj = {} } //事件发布 事件名 处理函数 on(eventName,handler){ //判断这个eventName是否存在 //如果当前的事件名不存在 给他赋值一个空数组 if(!this.obj[eventName]){ this.obj[eventName] = [] } //将事件添加进去 this.obj[eventName].push(handler) } //事件执行 事件名 参数 emit(eventName,...arg){ //判断这个eventName是否存在 if(!this.obj[eventName]) return //获取这个事件里面所有的处理函数 执行这些处理函数 //遍历对应的处理函数数组 this.obj[eventName].forEach(handler=>{ //执行对应的处理函数 传入参数 handler.call(this,...arg) }) } //事件取消 事件名 处理函数 off(eventName,handler){ //判断这个eventName是否存在 if(!this.obj[eventName]) return //遍历对应的eventName里面处理函数数组 找到匹配的handler将他删除 this.obj[eventName].forEach((v,i)=>{ if(Object.is(v,handler)){ this.obj[eventName].splice(i,1) } }) } }
注意事项
emit执行他可以传参传给对应的on方法里面处理函数(vue中父传子的实现及bus传值的实现)
off调用一定要emit之前
观察者模式是vue2底层实现
代理模式(*)
概述:
在不改变原本的类的基础上,对于对象进行功能加强,代理模式代理出来的是对象
核心关键词
被代理对象
代理对象
操作内容
代理的实现;在js es7新增了一个Proxy的类 这个类专门用来做代理
Proxy的使用
let obj={ name:'jack', age:18 } //新建代理对象(通过proxy的构造) let proxy=new Proxy(obj,{ get(target,attribute,proxyObj){ console.log('调用了get'); if(attribute=='name'){ return '姓名为'+target[attribute] }else if(attribute=='age'){ return target[attribute]+'岁' } return target[attribute] }, set(target,attribute,value,proxyObj){ console.log('调用了set'); target[attribute]=value }, defineProperty(target,attribute,descriptor){ console.log('新的属性定义'); console.log(descriptor); }, deleteProperty(target,attribute,proxyObj){ console.log('删除属性'); delete target[attribute] } }) console.log(proxy.name); console.log(proxy.age); proxy.name='你好' console.log(proxy.name); // delete proxy.name console.log((proxy.name)) console.log(obj);
总结
Proxy是一个es7新增的一个类 他返回的是一个对象
Proxy里面传入被代理对象和对应的处理对象
处理对象包含4个方法(get set defineProperty deleteProperty)
Proxy里面实际操作是被代理对象 (如果在里面操作代理对象会造成栈溢出)
代理对象和被代理对象不是一个对象 但是操作的内容是一个都是被代理对象
Proxy是vue3的底层实现之一
适配器模式
概述
将旧的的内容进行新的适配,在原本的基础上做兼容处理。
常用的业务场景
旧的接口替换新的接口(在不改变原本内容的情况下完成替换)
表单验证 (根据场景切换相关的验证)
示例
家庭用电最大的功率为22v
接入的电压220v
中间就需要继电器(适配口)
代码实现
class phone{ constructor(){ } fn(){ return 22 } } class Adaptive{ constructor(){ } fn(){ return '220转为'+new Phone().fn() } } //实际使用的是对于的适配的内容 new Adaptive().fn()
标签:24,console,log,处理函数,eventName,obj,new,设计模式,day From: https://www.cnblogs.com/zmfhtml5/p/16852461.html