javascript设计模式学习笔记二

2. 接口

  接口是面向对象JavaScript程序员的工具箱中最有用的工具之一。GoF在《设计模式》一书中提出的可重用面向对象设计的第一条原则就说道:“针对接口而不是实现编程”,这个概念的基本性由此可见一斑。

  问题在于,JavaScript中没有内置的创建或实现接口的方法。他也没有内置的方法可以用于判断一个对象是否实现了另一个对象相同的一套方法,这种对象很难互换使用。好在JavaScript有这出色的灵活性,因此添加这些特性并非难事。

  先讨论在JavaScript中实现接口的各种方法,最后设计出一个可重用的类,用于检查对象是否具有必要的方法。

2.1 什么是接口

  接口提供了一种用以说明一个对象应该具有哪些方法的手段。尽管它可以表明(或至少是暗示)这些方法的语义,但它并不规定这些方法应该如何实现。例如,如果一个接口包含一个名为setName的方法,那么你有理由认为这个方法的实现应该具有一个字符串参数,并且会把这个参数赋给一个name变量。

  有了这个工具,你就能按这个对象提供的特性对它进行分组。例如,即使一批对象彼此存在着极大的差异,只要它们都实现了Comparable接口,那么在obj.compare(anotherObject)方法中就可以互换使用这些对象。你还可以使用接口开发不同的类之间的共同性。如果把原本要求以一个特定的类为参数的函数改为要求以一个特定的接口为参数函数,那么任何实现了该接口的对象都可以作为参数传递给它。这样一来,彼此不想关的对象也可以被同等对待。

2.1.1 接口之利

  既定的一批接口具有自我描述性,并能促进代码的重用。接口可以告诉程序员一个类实现了哪些方法,从而帮助其他使用这个类。如果你熟悉一个特定的接口,那么久已经知道如何使用任何实现了它的类,从而更有可能重用现有的类。

  接口还有助于稳定不同的类之间的通信方式。如果事先知道了接口,你就能减少在集成两个对象的过程中出现问题。

  测试和调试因此也能变得更轻松。在JavaScript这种弱类型语言中,类型不匹配错误很难追踪。使用接口可以让这种错误的查找变得更容易一点,因为此时如果一个对象不像所要求的类型,或者没有实现必要方法,那么你会得到包含有用信息的明确的错误提示。这样一来,逻辑错误可以被限制在方法自身,而不是在对象的构成之中。接口还能让代码变得更稳固,因为对接口的任何改变在所有实现他的类中都必须体现出来。如果接口添加了一个操作,而某个实现他的类并没有相应地添加这个操作,那么你肯定会立即见到一个错误。

扫描二维码关注公众号,回复: 11254114 查看本文章

2.1.2 接口之弊

  接口并非没有缺点。JavaScript是一种具有极强的表现力的语言,这主要得益于其弱类型的特点。而接口的使用则在一定程度上强化了类型的作用。这降低了语言的灵活性。

  JavaScript并没有提供对接口的内置支持,而试图模仿其他语言内置的功能总会有一些风险。JavaScript中没有Interface这个关键词,因此,不管你用什么方法实现接口,他总是与c++和java这些语言中所用的方法大相径庭,这加大了初涉JavaScript时所遇到的困难。

  JavaScript中任何实现接口的方法都会对性能造成一些影响,再某种程度上这得归咎于额外的方法调用的开销。我们的实现方法中使用了两个for循环来遍历所需要的每一个接口中的每一个方法。对于大型接口和需要实现许多不同的接口对象,这种检查可能要花点时间,从而对性能造成负面影响。如果你在乎这个问题,那么可以在开发完成之后剔除这种代码,或者将其执行与一个调式标志关联起来,这样在运营环境中他就不会执行。但要注意不要过早进行优化处理。firebug这类性能分析器可以帮助你判断是否真有必要剔除接口的代码。

  接口使用中最大的问题在于,无法强迫其他程序员遵守你定义的接口。在其他语言中,接口的概念是内置的,如果某人定义了实现一个接口的类,那么编译器会确保该类的确实现了这个接口。而在JavaScript中则必须用手工的办法保证某个类实现了一个接口。编码规范和辅助类可以提供一些帮助,但无法彻底根除这个问题。如果项目的其他程序员不认真对待接口,那么这些接口的使用是无法得到强制性的保证的。除非项目的所有人都同意使用接口并对其进行检查,否则接口的很多价值都无从体现。

2.2  在JavaScript中模仿接口

  下面我们将探讨在JavaScript中模仿接口的三种方法:注释法、属性检查法和鸭式辩型法。没有哪种技术是完美的,但三者结合使用基本上可以令人满意。

2.2.1 用注释描述接口

  用注释模仿接口是最简单的方法,但效果确实最差的。这种方法模仿其他面向对象语言中的做法,使用了interface和implements关键字,但把它们放在注释中,以免引起语法错误。下面的示例演示了如何把这些关键字添加到代码中以描述所要求的方法:

 1 /*
 2 
 3  interface Composite {
 4    function add(child);
 5    function remove(child);
 6    function getChild(index);
 7  }
 8 
 9  interface FormItem {
10    function save();
11 }
12 
13 */
14 
15 var CompositeForm = function(id, method, action) { // implements Composite, FormItem
16    ...
17 };
18 
19 // Implement the Composite interface.
20 CompositeForm.prototype.add = function(child) {
21   ...
22 };
23 CompositeForm.prototyppe.remove = function(child) {
24   ...
25 };
26 CompositeForm.prototyppe.getChild = function(index) {
27   ...
28 };
29 
30 // Imlement the FormItem interface.
31 CompositeForm.prototyppe.save = function(child) {
32   ...
33 };
View Code

  

猜你喜欢

转载自www.cnblogs.com/wei-dong/p/12943358.html
今日推荐