js 设计模式

 

 

js 设计模式
 
 
 
1.什么是设计模式:
 
 
设计模式的定义:在面向对象软件设计过程种针对特定的问题的简洁而优雅的解决方案。就是给面向对象软件开发中一些 好的设计取个名。
 
好的设计是什么:代码复用高,可靠性强 (性能优),可维护好
 
设计模式的意义:
  • 模式为常见问题提供了行之有效的解决方案:模式提供了解决特定问题的优化模板;
  • 模式旨在重用:它们具备通用性,适合于各种问题。
 
 
 
2.为什么要给好设计取名?
 
 
好处:
 
1. 方便我们更好的传播和学习 ,记忆。
 
2. 模式交流更快速,降低沟通成本,提高工作效率当遇到一个问题时,知道这是哪种设计模式去解决
 
3. 吹牛逼
 
 
3.设计模式基础
 
一个程序的设计总是可以分为 可变部分和不变的部分;找出可变部分,将其封装,剩下的不变和稳定部分就非常容易复用。
 
所有设计模式的实现都遵循一条原则:找出程序中变化的地方,将变化封装起来。
 
JavaScript是一门面向对象语言,设计模式通过对面向对象的特征封装继承组合多态等技术的反复使用。
 
 
 
4.我们所了解的设计模式,还记得哪些?
 
 
单例模式、策略模式、代理模式、迭代器模式、发布-订阅模式、命令模式、组合模式、模板方法模式、享元模式、职责链模式、中介者模式、装饰者模式、状态模式、适配器模式、等等
 
 
 
5.这些常用模式分别适用于哪些场景?
 
 
设计模式
特点
案例
单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
典型案例:弹框
策略模式
根据不同参数可以命中不同的策略,
定义一系列的算法,把它们一个个封装起来。
在现实中,很多时候也有多种途径到达同一个目的地。比如我们要去某个地方旅游, 可以根据具体的实际情况来选择出行的线路。 1. 如果没有时间但是不在乎钱,可以选择坐飞机。 2.如果没有钱,可以选择坐大巴或者火车。 3 如果再穷一点,可以选择骑自行车。
 
很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。例如,绩效为 S 的人年 终奖有 4 倍工资,绩效为 A 的人年终奖有 3 倍工资,而绩效为 B 的人年终奖是 2 倍工资。假设财 务部要求我们提供一段代码,来方便他们计算员工的年终奖。
 
代理模式
代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
虚拟代理图片预加载
如果直接给某个 img 标签节点设置 src 属性,由于图片过大或者网络不佳,图片的位置往往有段时间会是一片空白。常见的做法是先用一张loading 图片占位,然后用异步的方式加载图片,等图片加载好了再把它填充到 img 节点里,这种场景就很适合使用虚拟代理。
迭代器模式
能获取聚合对象的顺序和元素
 
发布-订阅模式
PubSub
适用场景:一个网站,有好几个模块都需要获取用户信息后,进行渲染显示。在未用此种设计模式之前,我们会想着在获取用户信息的ajax成功回调函数中,写代码,渲染各个模块。但是这样做会导致,我们新增一个模块,需要去修改之前ajax的回调函数,加入新增部分的处理。而一个团队中,可能ajax回调函数部分是同事A做的,而新增模块是同事B负责的,其实B具体要做什么事情,A并不需要知道,A只需要告诉你,我已经拿到用户信息了,你们想干嘛就干嘛吧。那么这时候A提供出一个接口供其他需要它的人来订阅,在A完成任务后,告诉之前这些跟它打过招呼的模块,我把这些对你们有用信息传给你们,具体后续的事情由你们自己来决定。这就是发布-订阅模式。
命令模式
不同对象间约定好相应的接口
 
组合模式
组合模式在对象间形成一致对待的树形结构
 
模板方法模式
父类中定好执行顺序
 
享元模式
减少创建实例的个数
 
职责链模式
通过请求第一个条件,会持续执行后续的条件,直到返回结果为止
一系列可能会处理请求的对象被连接成一条链,请求在这些对象之间依次传递,直到遇到一个可以处理它的对象。请求发送者只需要知道链中的第一个节点。ps:可以将业务代码从if/else中释放出来,便于程序的扩展。
业务例子:公司针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过 500 元定金的用户会收到 100 元的商城优惠券, 200 元定金的用户可以收到 50 元的优惠券,而之前没有支付定金的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。
中介者模式
对象和对象之间借助第三方中介者进行通信
试想一下这个场景:一个手机购买界面,有选择手机颜色,大小,型号等下拉框及输入框。每当用户进行操作后,要实时回显用户的操作,并且在某一项未选择的时候,确认按钮应该是被禁用状态。
如果把这些内容都写在操作的回调函数中,比如:在选择手机颜色onselect事件中,写很多逻辑代码。那这样就不利于程序的扩展。在以后新增了某个选项,则需要在每个输入框的回调函数中增加对此新增的下拉框的判断。
所以我们应该把逻辑代码分离出来。交由中介者去完成判断。对于新增的业务,也只需要改中介者这个对象中的业务代码。在所有输入框或下拉框的回调事件中,我们只需向中介者发个请求,告诉它,我现在变化了。中介者接收到这个信号后,会自动做一系列的处理判断。
 
装饰者模式
动态地给函数赋能
 
状态模式
每个状态建立一个类,状态改变会产生不同行为
 
适配者模式
一种数据结构改成另一种数据结构
 
 
 

6.函数 节流/防抖 属于哪种设计模式?

 
 
函数节流:
 
JavaScript 中大多数情况都是用户主动出发函数,除非函数本身的实现不合理,否则一般不会遇到跟性能相关的问题,少数情况下,函数不是由用户直接触发控制,可能被频繁调用造成严重的性能问题。比如:
 
 
window.addEventListener('scroll', function(e) {
// do something...
});
 
 
上述事件1秒种触发很多次,并且常常操作DOM节点,非常损耗性能,浏览器会因此吃不消而卡顿;实际我们不需要触发如此高的频率因此我们可以在一段时间内忽略掉一些执行次数
 
 
节流原理:
 
如果持续触发事件,可每隔一段时间只执行一次,使用定时器实现节流。
 
将即将被执行的函数用 setTimeout 函数延迟一段时间执行,如果该定时器未执行完成则忽略接下下来的需被执行的函数。
 
function throttle(func,wait) {
 
let timer, firstFlag = true; //第一次立即执行
 
return function(...args) {
if(timer) return false; // 如果存在定时器这不执行
let that = this;
 
if(firstFlag){
firstFlag = false;
return func.apply(that,args);
}
 
 
timer = setTimeout(function(){
clearTimeout(timer);
timer = null;
func.apply(that,args);
},wait)
}
}
 
 
window.addEventListener('scroll', throttle(function(e) {
console.log(e)
},1000));
 
 
 
函数防抖
 
 
和节流一定时间段内只调用一次事件处理函数不同,防抖是一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。(用户不再触发对应事件才执行一次事件)
 
 
function debounce(func,wait) {
let timer;
return function(...args) {
let that = this;
clearTimeout(timer);
timer = setTimeout(function(){
func.apply(that,args)
},wait)
}
}
window.addEventListener('scroll', debounce(function(e) {
console.log(e)
},1000));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2020-07-20 15:09  贪玩玩的小狮子  阅读(31)  评论(0编辑  收藏  举报