作者 | 考拉海购前端团队链接 | https://juejin.im/post/59df4f74f265da430f311909设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案当然我们可以用一个通俗的说法:设计模式是解决某个特定场景下对某种问题的解决方案。因此,当我们遇到合适的场景时,我们可能会条件反射一样自然而然想到符合这种场景的设计模式。比如,当系统中某个接口的结构已经无法满足我们现在的业务需求,但又不能改动这个接口,因为可能原来的系统很多功能都依赖于这个接口,改动接口会牵扯到太多文件。因此应对这种场景,我们可以很快地想到可以用适配器模式来解决这个问题。下面介绍几种在JavaScript中常见的几种设计模式:

1、单例模式

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。适用场景:一个单一对象。比如:弹窗,无论点击多少次,弹窗只应该被创建一次。

class CreateUser {    constructor(name) {        this.name = name;        this.getName();    }    getName() {         return this.name;    }}// 代理实现单例模式var ProxyMode = (function() {    var instance = null;    return function(name) {        if(!instance) {            instance = new CreateUser(name);        }        return instance;    }})();// 测试单体模式的实例var a = new ProxyMode("aaa");var b = new ProxyMode("bbb");// 因为单体模式是只实例化一次,所以下面的实例是相等的console.log(a === b);    //true

2、策略模式

策略模式的定义:定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。策略模式的目的就是将算法的使用算法的实现分离开来。一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类(可变),策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类Context(不变),Context接受客户的请求,随后将请求委托给某一个策略类。要做到这一点,说明Context中要维持对某个策略对象的引用。

/*策略类*/var levelOBJ = {    "A": function(money) {        return money * 4;    },    "B" : function(money) {        return money * 3;    },    "C" : function(money) {        return money * 2;    } };/*环境类*/var calculateBouns =function(level,money) {    return levelOBJ[level](money);};console.log(calculateBouns('A',10000)); // 40000

3、代理模式

代理模式的定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。常用的虚拟代理形式:某一个花销很大的操作,可以通过虚拟代理的方式延迟到这种需要它的时候才去创建(例:使用虚拟代理实现图片懒加载)图片懒加载的方式:先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。

var imgFunc = (function() {    var imgNode = document.createElement('img');    document.body.appendChild(imgNode);    return {        setSrc: function(src) {            imgNode.src = src;        }    }})();var proxyImage = (function() {    var img = new Image();    img.onload = function() {        imgFunc.setSrc(this.src);    }    return {        setSrc: function(src) {            imgFunc.setSrc('./loading,gif');            img.src = src;        }    }})();proxyImage.setSrc('./pic.png');

使用代理模式实现图片懒加载的优点还有符合单一职责原则。减少一个类或方法的粒度和耦合度。

4、中介者模式

中介者模式的定义:通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。例如:现实生活中,航线上的飞机只需要和机场的塔台通信就能确定航线和飞行状态,而不需要和所有飞机通信。同时塔台作为中介者,知道每架飞机的飞行状态,所以可以安排所有飞机的起降和航线安排。中介者模式适用的场景:例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。

var goods = {   //手机库存    'red|32G': 3,    'red|64G': 1,    'blue|32G': 7,    'blue|32G': 6,};//中介者var mediator = (function() {    var colorSelect = document.getElementById('colorSelect');    var memorySelect = document.getElementById('memorySelect');    var numSelect = document.getElementById('numSelect');    return {        changed: function(obj) {            switch(obj){                case colorSelect:                    //TODO                    break;                case memorySelect:                    //TODO                    break;                case numSelect:                    //TODO                    break;            }        }    }})();colorSelect.onchange = function() {    mediator.changed(this);};memorySelect.onchange = function() {    mediator.changed(this);};numSelect.onchange = function() {    mediator.changed(this);};

5、装饰者模式

装饰者模式的定义:在不改变对象自身的基础上,在程序运行期间给对象动态地添加方法。例如:现有4种型号的自行车分别被定义成一个单独的类,如果给每辆自行车都加上前灯、尾灯、铃铛这3个配件,如果用类继承的方式,需要创建4*3=12个子类。但如果通过装饰者模式,只需要创建3个类。装饰者模式适用的场景:原有方法维持不变,在原有方法上再挂载其他方法来满足现有需求;函数的解耦,将函数拆分成多个可复用的函数,再将拆分出来的函数挂载到某个函数上,实现相同的效果但增强了复用性。例:用AOP装饰函数实现装饰者模式

Function.prototype.before = function(beforefn) {    var self = this;    //保存原函数引用    return function(){  //返回包含了原函数和新函数的 '代理函数'        beforefn.apply(this, arguments);    //执行新函数,修正this        return self.apply(this,arguments);  //执行原函数    }}Function.prototype.after = function(afterfn) {    var self = this;    return function(){        var ret = self.apply(this,arguments);        afterfn.apply(this, arguments);        return ret;    }}var func = function() {    console.log('2');}//func1和func3为挂载函数var func1 = function() {    console.log('1');}var func3 = function() {    console.log('3');}func = func.before(func1).after(func3);func();

本文完~

相关推荐

【JS进阶深挖】完全弄懂数据类型转换(下)

绝大部分的开源项目都投入TypeScript了!你呢?

【收藏系列】JS灵魂之问(下) - 附个人成长经验分享

【收藏系列】JS灵魂之问, 是否有offer看你接到多少个(中)

【收藏系列】JS灵魂之问, 请问你能接得住几个?(上)

【大厂面试】20道超高频题目【JS进阶深挖】完全弄懂数据类型转换(上)前端架构师最终面试题!48道题JS继承题目【面试官再也难不倒你了系列】神奇的arguments笔试题【一天突破一个知识点】45道Promise面试题【面试官再也难不倒你了系列】40道this面试题!面试官再也难不到你了!

在看点这里

javascript 保存原函数_前端工程师必须掌握的几个JavaScript设计模式及场景应用相关推荐

  1. 前端传中文文件名_前端工程师需要掌握哪些知识,web前端开发规范总结

    Web前端作为开发团队中不可或缺的一部分,需要按照相关规定进行合理编写(一部分不良习惯可能给自己和他人造成不必要的麻烦).不同公司不同团队具有不同的规范和文档.下面是根据不同企业和团队的要求进行全面详 ...

  2. 前端 流星特效_前端工程师流星

    前端 流星特效 As part of my daily web browsing routine, I follow a number of front-end blogs. I'm always a ...

  3. nginx 带宽_前端工程师不可不知的Nginx知识

    历史背景 互联网的全球化导致了互联网的数据量快速增长,加上在本世纪初摩尔定律在单核 CPU 上的失效,CPU 朝着多核方向发展,而 Apache 显然并没有做好多核架构的准备,它的一个进程同一时间只能 ...

  4. uni app 调用网络打印机_前端工程师 | 原生小程序坑点:uni-app到底好用在哪里?...

    要想知道uni-app开发好用在哪里,我们先看看uni-app的官网,下图 系统的介绍.框架.组件.api的使用都非常的详细,感兴趣的朋友可以去尝试尝试. 我们进图正题,首先和原生小程序来比较,其次和 ...

  5. picACG本地缓存目录_前端工程师必备之缓存问题

    缓存是个老生长谈的问题,对于前端工程师来讲更是我们的必修课.或许很多人会说我的项目并没有问题,根本不需要聊什么缓存.如果真的是这样,只能证明你前端道路才刚刚开始. 背景 小郭今天分享缓存的原因在于:公 ...

  6. python前端开发需要的工具_前端工程师都有用哪些比较靠谱的小工具?

    Wappalyzer 是一个用于识别网站使用的库和框架的工具.它也是一个 Chrome 插件,是目前为前端开发人员最有用的工具之一.下一次你想知道一个网站使用什么库,来创建一个特定的可视化功能,Wap ...

  7. vue 前端商城框架_前端工程师要掌握几个Vue框架

    vue是一套用于构建用户界面的渐进式JavaScript框架,简单说Vue是类似于view的前端框架. vue开发核心是关注视图层,同时它更加容易与第三方库结合,再者我们在现有的项目中可以直接整合一起 ...

  8. 前端和后端的英文_前端工程师一般都喜欢去哪些网站逛?

    看到有人问前端开发应该知道哪些网站,那我就来总结一下. 我先说一些程序员很通用的网站,再推荐一写前端程序员可以订阅的优质前端内容网站,如果对你有用,就点个赞呗~ 1. Google: 这个不用多说了吧 ...

  9. html请求接口_前端工程师吐后端工程师(第八讲)——接口的开发

    上一讲我们介绍了如何写让模板变量在页面上展示,本讲我们介绍一下后端开发工作中最常用的功能--接口.创建一个go_test4文件夹,然后把go_test3中的代码复制进去.然后打开main.go文件,进 ...

最新文章

  1. 机器人编程语言python-机器人编程语言有哪些?
  2. P3385 【模板】负环
  3. Oracle 11g 安装后续——开发工具篇
  4. QT的QGLShaderProgram类的使用
  5. 初识react中高阶组件
  6. GLog 初始化说明
  7. linux下的yum命令详解
  8. 学习笔记之七_第2层交换和生成树协议(STP)(CCNA知识考点)
  9. CAD软件中如何自定义CAD填充图案?
  10. 1m照片的宽和高是多少_照片常见标准尺寸大全
  11. 世界主要国家货币名称列表整理[外贸免费工具]
  12. excel Cell函数
  13. Makefile与前缀后缀相关函数suffix、basename、addsuffix、addprefix
  14. 无线电频谱和波段划分
  15. 如何设置IE为默认浏览器?如何设置谷歌chrome为默认浏览器?
  16. 【一江水 一家人】 盘龙区打造铸牢中华民族共同体意识盘龙江示范带
  17. 买服务器为何选择华为云?
  18. java中的mybatis作用_mybatis作用、基本使用、小结
  19. Day19JavaWeb【旅游项目】封装与设计***
  20. Playwirght深度入门

热门文章

  1. 获取和设置消息队列的属性msgctl,删除消息队列
  2. mysql数据库主从复制部署笔记
  3. 测试转开发,一个女孩子短短的工作心得
  4. Inside Dynamics Axapta源代码赏析(三)
  5. Python爬虫post一例
  6. h5 移动端 监听软键盘弹起、收起
  7. Laravel Cache 的缓存文件在到期后是否会自动删除
  8. 两个或多个线程执行完成之后继续执行之后的步骤,CountDownLatch与CyclicBarrier
  9. 第十篇 JVM核心机制之JVM运行和类加载全过程(五)
  10. Windows上基于快捷方式的Putty免密码登陆