不知道怎么提高代码可扩展性?来看看优秀框架源码中的这几种设计模式吧!

为什么要提高代码扩展性

我们写的代码都是为了一定的需求服务的,但是这些需求并不是一成不变的,当需求变更了,如果我们代码的扩展性很好,我们可能只需要简单的添加或者删除模块就行了,如果扩展性不好,可能所有代码都需要重写,那就是一场灾难了,所以提高代码的扩展性是势在必行的。怎样才算有好的扩展性呢?好的扩展性应该具备以下特征:

  1. 需求变更时,代码不需要重写。
  2. 局部代码的修改不会引起大规模的改动。有时候我们去重构一小块代码,但是发现他跟其他代码都是杂糅在一起的,里面各种耦合,一件事情拆在几个地方做,要想改这一小块必须要改很多其他代码。那说明这些代码的耦合太高,扩展性不强。
  3. 可以很方便的引入新功能和新模块。

怎么提高代码扩展性?

当然是从优秀的代码身上学习了,本文会深入AxiosNode.jsVue等优秀框架,从他们源码总结几种设计模式出来,然后再用这些设计模式尝试解决下工作中遇到的问题。本文主要会讲职责链模式观察者模式适配器模式装饰器模式。下面一起来看下吧:

职责链模式

职责链模式顾名思义就是一个链条,这个链条上串联了很多的职责,一个事件过来,可以被链条上的职责依次处理。他的好处是链条上的各个职责,只需要关心自己的事情就行了,不需要知道自己的上一步是什么,下一步是什么,跟上下的职责都不耦合,这样当上下职责变化了,自己也不受影响,往链条上添加或者减少职责也非常方便。

实例:Axios拦截器

用过Axios的朋友应该知道,Axios的拦截器有请求拦截器响应拦截器,执行的顺序是请求拦截器 -> 发起请求 -> 响应拦截器,这其实就是一个链条上串起了三个职责。下面我们来看看这个链条怎么实现:

// 先从用法入手,一般我们添加拦截器是这样写的 
// instance.interceptors.request.use(fulfilled, rejected)
// 根据这个用法我们先写一个Axios类。
function Axios() {
   
  // 实例上有个interceptors对象,里面有request和response两个属性
  // 这两个属性都是InterceptorManager的实例
  this.interceptors = {
   
    request: new InterceptorManager(),
    response: new InterceptorManager()
  };
}

// 然后是实现InterceptorManager类
function InterceptorManager() {
   
  // 实例上有一个数组,存储拦截器方法
  this.handlers = [];
}

// InterceptorManager有一个实例方法use
InterceptorManager.prototype.use = function(fulfilled, rejected) {
   
  // 这个方法很简单,把传入的回调放到handlers里面就行
  this.handlers.push({
   
    fulfilled,
    rejected
  })
}

上面的代码其实就完成了拦截器创建和use的逻辑,并不复杂,那这些拦截器方法都是什么时候执行呢?当然是我们调用instance.request的时候,调用instance.request的时候真正执行的就是请求拦截器 -> 发起请求 -> 响应拦截器链条,所以我们还需要来实现下Axios.prototype.request:

Axios.prototype.request = function(config) {
   
  // chain里面存的就是我们要执行的方法链条
  // dispatchRequest是发起网络请求的方法,本文主要讲设计模式,这个方法就不实现了
  // chain里面先把发起网络请求的方法放进去,他的位置应该在chain的中间
  const chain = [dispatchRequest, undefined];
  
  // chain前面是请求拦截器的方法,从request.handlers里面取出来放进去
  this.interceptors.request.handlers.forEach(function unshiftRequestInterceptors(interceptor) {
   
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });
  
  // chain后面是响应拦截器的方法,从response.handlers里面取出来放进去
  this.interceptors.response.handlers.forEach(function pushResponseInterceptors(interceptor) {
   
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });
  
  // 经过上述代码的组织,chain这时候是这样的:
  // [request.fulfilled, request.rejected, dispatchRequest, undefined, response.fulfilled,  
  // response.rejected]
  // 这其实已经按照请求拦截器 -> 发起请求 -> 响应拦截器的顺序排好了,拿来执行就行
  
  let promise = Promise.resolve(config);   // 先来个空的promise,好开启then
  while (chain.length) {
   
    // 用promise.then进行链式调用
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
}

上述代码是从Axios源码中精简出来的,可以看出他巧妙的运用了职责链模式,将需要做的任务组织成一个链条,这个链条上的任务相互不影响,拦截器可有可无,而且可以有多个,兼容性非常强。

实例:职责链组织表单验证

看了优秀框架对职责链模式的运用,我们再看看在我们平时工作中这个模式怎么运用起来。现在假设有这样一个需求是做一个表单验证,这个验证需要前端先对格式等内容进行校验,然后API发给后端进行合法性校验。我们先分析下这个需求,前端校验是同步的,后端验证是异步的,整个流程是同步异步交织的,为了能兼容这种情况,我们的每个验证方法的返回值都需要包装成promise才行

// 前端验证先写个方法
function frontEndValidator(inputValue) {
   
  return Promise.resolve(inputValue);      // 注意返回值是个promise
}

// 后端验证也写个方法
function backEndValidator(inputValue) {
   
  return Promise.resolve(inputValue);      
}

// 写一个验证器
function validator(inputValue) {
   
  // 仿照Axios,将各个步骤放入一个数组
  const validators = [frontEndValidator, backEndValidator];
  
  // 前面Axios是循环调用promise.then来执行的职责链,我们这里换个方式,用async来执行下
  async <
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值