您当前的位置:首页 > 微信小程序开发笔记 >

信息隐藏和接口

0

在开发应用的过程中,代码的数量和复杂度都会不断增长。最终,代码基可能会变成一团乱麻,不过我们可以编写更简单的代码,让代码的执行流程更易于理解,避免出现这种状况。有一种方法能逐渐降低复杂度,即隐藏不必要的信息,不在接口中开放。这样就只有有关的信息才会开放,未开放的则是对使用者来说无关紧要的信息,通常被称为实现细节。我们不想开放的信息包括计算结果时使用的状态变量,或提供给随机数生成器的种子数。每个层面都要隐藏信息,每个模块中的每个函数都应该把对使用者无关的信息隐藏起来。做到这一点,就帮了共事的开发者和未来的自己一个忙:他们(和你自己)在弄清某个方法或模块的作用时不用过多地进行猜测了。

作为示例,下列代码清单演示了如何构建一个对象,并计算简单的平均值。这个清单使用了一个构造函数,而且扩充了原型,为Average 对象添加了add方法和calc方法。

function Average(){
  this.sum=0;
  this.count=0;
}
Average.prototype.add=function(value){
  this.sum+=value;
  this.count++;
}
Average.prototype.calc=function(){
  return this.sum/this.count;
}

然后,我们只需创建一个 Average 对象,向其中添加值,然后再计算平均值。这种实现方式有个问题,即你可能不想让人直接访问私有数据,例如 Average.count。或许你想使用我们即将介绍的技术隐藏这些值,不让使用这个API的人使用。不过,更简单的方式或许是完全不用这个对象,把它改成一个函数。我们可以使用 .reduce 方法(这是ES5新提供的方法,在Array原型中)实现一个累加器,把数组中的元素加在一起,然后再计算平均值:

function average(values){
  var sum=values.reduce(function(accumulator,value){
    return accumulator + value;
  }, 0);
  return sum / values.length;
}

这个函数的优点是完全符合我们的要求。它的参数是一个数组,返回结果为各元素的平均值,正如其名所示。而且,和前面使用原型实现的方式相比,它没有保存任何状态变量,有效隐藏了内部运作信息。我们称之为纯函数:其返回结果只取决于传入的参数,与不在参数中的状态变量、服务或对象都没关系。纯函数还有一个特性:除了返回值之外没有任何副作用。这两个特性结合在一起,让纯函数成为一种很好的接口——自成一体,而且易于测试。因为纯函数没有副作用,也没有外部依赖,所以你可以放心重构,只要不改变输入和输出之间的关系就行。

功能型工厂函数

除此之外,我们还可以使用功能型工厂函数(functional factory)实现。执行这种函数后会得到另一个函数,使用得到的这个函数就可以做我们想做的事。在工厂函数中声明的任何变量都只能在这个函数和内部的函数中使用,通过下列代码你会更好地理解工厂函数:

function averageFactory(){
  var sum=0;
  var count=0;
  return function(value){
    sum+=value;
    count++;
    return sum/count;
  };
}

sum 和 count 两个变量只能在 averageFactory 函数返回的函数实例中访问,而且各个实例只能访问自身上下文中声明的变量,不能访问其他实例的上下文。averageFactory 函数可以理解成一个饼切,切出的饼干(函数)接受一个值,然后返回(目前为止得到的)累加值的平均数。下列示例说明了如何使用这个工厂函数:

var avg = averageFactory();
avg(1);//输出1
avg(3);//输出2

使用饼切切饼干时不会影响已经切好的饼干,类似地,创建多个实例也不会影响已经创建的实例。这种编程方式和前面使用原型的方式类似,不过现在除了实现主体,其他地方都不能访问 sum 和 count 变量。使用者无法访问这些变量,实际上就是把它们当作API的实现细节了。实现细节不仅会带来干扰,还有可能导致安全隐患,因为我们不想让外部世界修改组件的内部状态。

建站咨询

在线咨询真诚为您提供专业解答服务

咨询热线

137 1731 25507×24小时服务热线

微信交流

二维码终于等到你,还好我没放弃
返回顶部