javascript中模仿接口(interface)
没想到javascript还可以模拟接口,顿时觉得js更加强大,所以把《javascript设计模式》的内容摘录出来,供大家学习,内容稍有改动.
1.在javascript中引入接口的好处:
接口具有自我描述性,可以促进代码的重用;有利于不同的类之间进行通信,在大型项目中尤其有用;有利于代码的测试和调试。
2.引入接口的弊端
接口的引入强化了类型的作用,降低了语言的灵活性;带来额外的开销;无法强迫其他程序员遵守你定义的接口。
3.模仿接口的方法
方法1:用注释描述
View Code
1 /* 2 interface composite{ 3 function add(child); 4 function remove(child); 5 function getChild(index); 6 } 7 interface FormItem{ 8 function save(); 9 } 10 */ 11 var CompositeForm = function(){ 12 ... 13 } 14 15 CompositeForm.prototype = { 16 add: function(child){...}, 17 remove: function(child){...}, 18 getChild: function(index){...}, 19 save: function(){...} 20 }
该方法的不足:主要属于程序文档的范围,对接口的遵守完全依靠自觉。
方法2:用属性检查模拟接口
View Code
/* interface composite{ function add(child); function remove(child); function getChild(index); } interface FormItem{ function save(); } */ var CompositeForm = function(){ this.implementsInterfaces = ['Composite','FormItem']; ... } function addForm(formInstance){ if(! implements(formInstance,'Composite','FormItem')){ throw new Error('object does not omplement a required interface'); } ... } function implements(object){ for(var i=1;i<arguments.length;i++){ var interfaceName = arguments[i]; var found = false; for(var j=0;j<object.implementsInterfaces.length;j++){ if(object.implementsInterfaces[j] === interfaceName){ found = true; break; } } if(! found){ return false; //an interface was not found } } return true; }
该方法的特点是显示地声明自己支持什么接口,但是并未确保类真正实现了自称的接口。
方法3.鸭式变型模拟接口
首先是Interface类的定义
View Code
1 var Interface = function(name,methods){ 2 if(arguments.length != 2){ 3 throw new Error('....'); 4 } 5 this.name = name; 6 this.methods = []; 7 for(var i=1; i< methods.lenght;i++){ 8 if(typeof method[i] !== 'string'){ 9 throw new Error(...); 10 } 11 this.methods.push(methods[i]); 12 } 13 } 14 Interface.ensureImplements = function(object){ 15 if(arguments.length < 2){ 16 throw new Error(...); 17 } 18 for(var i=1;i<arguments.lenght;i++){ 19 var interfaceName = arguments[i]; 20 if(interfaceName.constructor !==Interface){ 21 throw new Error(...); 22 } 23 for(var j=0; j<interfaceName.methods.length;j++){ 24 var method = interfaceName.methods[j]; 25 if(!object[method] || typeof object[method] !== 'function'){ 26 throw new Error(...); 27 } 28 } 29 } 30 }
接下来模拟接口:
View Code
1 /* 2 interface composite{ 3 function add(child); 4 function remove(child); 5 function getChild(index); 6 } 7 interface FormItem{ 8 function save(); 9 } 10 */ 11 var Composite = new Interface('Composition',['add','remove','getChild']); 12 var FormItem = new Interface('FormItem',['save']); 13 14 var CompositeForm = function(){ 15 ... 16 } 17 18 function addForm(formInstance){ 19 Interface.ensureImplements(formInstance,Composite,FormItem); 20 ... 21 }
特点:可以保证强制实施类实现接口,但是缺少自我描述,同时还需要一个辅助类(Interface)和辅助函数(ensureImplements)。
4.结论:
模拟接口最好的办法同时使用注释和鸭式变型方法。其实模拟接口不是最难的,难点在于何时使用接口。