Fork me on GitHub

JS常用设计模式总结

写在前面

设计模式,是一套经过前人总结、业务验证并适合于特定业务开发的代码组织方式,可能会有一些同学会认为设计模式没有用,我这里需要指出设计模式并不是万能的只适合于特定业务场景的开发(对我们的业务开发起到一定的指导作用,所有设计模式的目的都是让开发者编写可维护、易扩展的代码),其实你日常开发中或多或少都使用过设计模式,只是你不知道名字而已(如,绑定事件和触发事件这就是一个简单的发布-订阅模式)。
本文所有设计模式都是使用 JavaScript 语言书写,这些案例都是较为基础的,目的是帮助前端同学更好的理解设计模式。
为了你更好的理解设计模式,你需要了解设计模式的六大原则:单一职责原则、开放封闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则,可以看这篇设计模式六大原则
本文将同步发布于Blog、掘金、segmentfault、知乎等处,如果本文对你有帮助,记得为我得到我的个人技术博客项目给个star哦。

设计模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

SOLID原则

设计模式一般需要满足下列原则【2019-01-09更新】
SOLID 是几个单词首字母组合而来,分别表示 单一功能原则、开闭原则、里氏替换原则、接口隔离原则以及依赖反转原则。
单一功能原则:如果一个类干的事情太多太杂,会导致后期很难维护。我们应该厘清职责,各司其职减少相互之间依赖。
开闭原则:“开”指的就是类、模块、函数都应该具有可扩展性,“闭”指的是它们不应该被修改。也就是说你可以新增功能但不能去修改源码。
里氏替换原则:名字很唬人,其实道理很简单,就是子类不要去重写父类的方法。
接口隔离原则:JavaScript 几乎没有接口的概念,所以这条原则很少被使用。官方定义是“客户端不应该依赖它不需要的接口”,也就是接口最小化,把接口解耦。
依赖反转原则:高层次模块不能依赖低层次模块,它们依赖于抽象接口,抽象接口不能依赖具体实现,具体实现依赖抽象接口。总结下来就两个字,解耦。

工厂模式(Factory)

定义:简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例通常都拥有相同的接口(属性和方法)。
举例:计算器(加、减、乘、除)、自行车售卖(山地、公路)、饮料机(咖啡、牛奶、水)、RPG中职业(战士、法师、射手)
需要详细了解该模式,请访问该链接

单例模式(Singleton)

定义:单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
举例::模态框、登录控件、注销控件
需要详细了解该模式,请访问该链接

策略模式(Strategy)

定义:策略模式包括两个部分,算法的使用部分(不变的)和算法的实现部分(可变的)。
举例:表单效验(是否为空、长度、手机号、邮箱等等)、计算年终奖(工资、效绩)
需要详细了解该模式,请访问该链接

代理模式(Proxy)

定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。代理对象和本体对象实现了同样的接口,并且会把任何方法调用传递给本体对象;
举例: 图片预加载、图片懒加载、合并HTTP请求(代理收集一定时间内的所有HTTP请求,然后一次性发给服务器)、惰性加载(通过代理处理和收集一些基本操作,然后仅在真正需要本体的时候才加载本体)、缓存代理(缓存请求结果、计算结果)
需要详细了解该模式,请访问该链接

中介者模式(Mediator)

定义:中介者模式的作用就是解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介者对象即可。中介者使各对象之间耦合松散,而且可以独立地改变它们之间的交互。中介者模式使网状的多对多关系变成了相对简单的一对多关系。
举例:手机购买页面(颜色、数量、内存、价格)、MVC模式(控制层便是位于表现层与模型层之间的中介者)
需要详细了解该模式,请访问该链接

装饰者模式(Decorator)

定义:装饰者(decorator)模式能够在不改变对象自身的基础上,在程序运行期间给对象动态的添加职责。装饰者用于通过重载方法的形式添加新功能,该模式可以在被装饰者前面或者后面加上自己的行为以达到特定的目的。与继承相比,装饰者是一种更轻便灵活的做法。
举例:雷霆战机(吃道具的例子)
需要详细了解该模式,请访问该链接

发布订阅模式(Observer)

定义:对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
举例:模块通信、事件绑定与触发、售楼中心
需要详细了解该模式,请访问该链接

适配器模式(Adapter)

定义:适配器模式(Adapter)是将一个类(对象)的接口(方法或属性)转化成客户希望的另外一个接口(方法或属性),适配器模式使得原本由于接口不兼容而不能一起工作的那些类(对象)可以一些工作。速成包装器(wrapper)。
举例:常用于接口适配、兼容多个库(如Prototype库的$函数和YUI的get方法)
需要详细了解该模式,请访问该链接

迭代器模式(Iterator)

定义:迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
举例:jquery的$.each()、
需要详细了解该模式,请访问该链接

桥接模式(Bridge)

定义:桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化。
举例:用桥接模式联结多个类、事件监控
需要详细了解该模式,请访问该链接

外观模式(Facade)

定义:外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口使得这一子系统更加容易使用。
举例:兼容浏览器事件绑定、兼容浏览器阻止冒泡、默认事件
需要详细了解该模式,请访问该链接

访问者模式(Visitor)

定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
举例:
需要详细了解该模式,请访问该链接

模版方法模式

定义:模版方法模式由二部分组成,第一部分是抽象父类,第二部分是具体实现的子类,一般的情况下是抽象父类封装了子类的算法框架,包括实现一些公共方法及封装子类中所有方法的执行顺序,子类可以继承这个父类,并且可以在子类中重写父类的方法,从而实现自己的业务逻辑。
举例:泡饮品(茶 和 coffee)、公司面试(百度面试 和 阿里面试)
需要详细了解该模式,请访问该链接

组合模式(Composite)

定义:组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象(子对象)和组合对象的使用具有一致性。
举例:文件扫描(目录为组合对象和文件为子对象)、dom节点操作
需要详细了解该模式,请访问该链接

备忘录模式(Memento)

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态。
举例:分页控件、撤销组件
需要详细了解该模式,请访问该链接

职责链模式(Chain of Responsibility)

定义:职责链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
举例:挤公交车递钱(只有售票员可以收钱)、交押金预定手机
需要详细了解该模式,请访问该链接

状态模式(State)

定义:状态模式(State)定义一个对象,这个对象可以通过管理其状态从而使得应用程序作出相应的变化。状态模式是一个非常常用的设计模式,它主要有两个角色组成(环境类、状态类)。
举例:文件下载(开始、暂停、完成、失败等)、红绿灯
需要详细了解该模式,请访问该链接

享元模式(Flyweight)

定义:享元模式是一种用于性能优化的模式,如果系统中因为创建了大量类似的对象而导致内存不足或占用过高这种模式就非常有用了(具体做法缓存对象从而达到重复利用)。
举例:内衣厂展示许多商品展示、地图应用(对象池)
需要详细了解该模式,请访问该链接

-------------本文结束感谢您的阅读,如果本文对你有帮助就记得给个star-------------
Donate comment here