前端5大常见设计模式、代码一看你就懂!( 二 )

总结:在简单工厂中,如果我们新增加一个用户类型,需要修改两个地方的代码,一个是增加新的用户构造函数,一个是在逻辑判断中增加对新的用户的判断,而在抽象工厂方法中,我们只需要在UserFactory.prototype中添加就可以啦 。

前端5大常见设计模式、代码一看你就懂!

文章插图
 
二、单例模式定义:是保证一个类只有一个实例,并且提供一个访问它的全局访问点 。
需求:一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的window对象、登录浮窗等 。
实现:用一个变量标识当前是否已经为某个类创建过对象,如果是,则在下一次获取这个类的实例时,直接返回之前创建的对象 。
优点:
  • 可以用来划分命名空间,减少全局变量的数量
  • 可以被实例化,且实例化一次,再次实例化生成的也是第一个实例
下面举个例子,在js中,我们可以使用闭包来创建实现这种模式:
var single = (function(){ var unique; function getInstance(){ // 如果该实例存在,则直接返回,否则就对其实例化 if( unique === undefined ){ unique = new Construct(); } return unique; } function Construct(){ // ... 生成单例的构造函数的代码 } return { getInstance : getInstance }})();【前端5大常见设计模式、代码一看你就懂!】总结:在上面的代码中,我们可以使用single.getInstance来获取到单例,并且每次调用均获取到同一个单例,在我们平时的开发中,我们也经常会用到这种模式,比如当我们单击登录按钮的时候,页面中会出现一个登录框,而这个浮窗是唯一的,无论单击多少次登录按钮,这个浮窗只会被创建一次,因此这个登录浮窗就适合用单例模式 。
三、代理模式代理模式主要是为其他对象提供一种代理以控制对这个对象的访问,主要解决在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上,在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层 。
代理模式最基本的形式是对访问进行控制,代理对象和另一个对象(本体)实现的是同样的接口,实际上工作还是本体在做,它才是负责执行所分派的任务的那个对象或类,代理对象所做的不外乎节制对本体的访问,代理对象并不会在另一对象的基础上添加方法或修改其方法,也不会简化那个对象的接口,它实现的接口与本体完全相同,所有对它进行的方法调用都会被传递给本体 。
(function(){ // 示例代码// 目标对象,是真正被代理的对象 function Subject(){} Subject.prototype.request = function(){};/** * 代理对象 * @param {Object} realSubject [持有被代理的具体的目标对象] */ function Proxy(realSubject){ this.realSubject = readSubject; } Proxy.prototype.request = function(){ this.realSubject.request(); };}());总结:在上面的代码中,Proxy可以控制对真正被代理对象的一个访问,在代理模式中,比较常见的就是虚拟代理,虚拟代理用于控制对那种创建开销很大的本体的访问,它会把本体的实例化推迟到有方法被调用的时候,比如说,现在我们假设PublicLibrary的实例化很慢,不能在网页加载的时候立即完成,我们可以为其创建一个虚拟代理,让它把PublicLibrary的实例化推迟到必要的时候,比如说我们在前端中经常用到的图片懒加载,就可以用虚拟代理;
四、观察者模式如果大家学过一些像vue,react这些框架,相信大家对观察者模式一定很熟悉,现在很多mvvm框架都用到了观察者模式这个思想,观察者模式又叫做发布—订阅模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知和更新,观察者模式提供了一个订阅模型,其中对象订阅事件并在发生时得到通知,这种模式是事件驱动的编程基石,它有利益于良好的面向对象的设计
定义:对象间的一种一对多的依赖关系 。
需求:当一个对象的状态发生变化时,所有依赖于他的对象都将得到通知 。
优点:时间上的解耦,对象之间的解耦 。
实现: