JavaScript-设计模式之接口的实现
2016-06-11 00:23
465 查看
在JS中,并没有真正意义上的接口,我们只能通过模拟的方式实现接口的效果,使用接口可以促进代码的重用,降低代码之间的耦合度,减少代码错误及查找错误原因,坏处就是加大代码量,而且并不能强制程序员实现接口。JS中模拟接口的方式有三种。
1、首先定义一个用于创建接口的函数
2、使用如上函数声明2个接口并创建对象实现接口方法
3、编写方法检测对象是否实现接口的方法
4、检测对象是否实现的指定接口对象中的方法
实际使用中可以结合第一种方式一起使用
第一种:注释的方式
这种方式是使用注释显示的告诉程序员需要实现哪些接口,这种方式完全靠程序员的自觉性,并且是否真正实现了接口并不能检查,对代码的调试不起任何帮助,相反正因为这种方式,不会对代码性能产生影响。/** * 基于注释的实现-接口代码在注释中,对于程序不起任何作用,仅仅是写给程序员看。 * * 这是一个GAME接口,具备一个playGames方法 *public interface Game { * public void playGames(); * } * * * 这是一个Food接口,具备一个eat方法 * public interface Food { * public void eat(); * } */ var Person = function(name) { this.name = name; }; //根据注释的内容,自觉地实现接口中的方法 Person.prototype.playGames = function() { alert(this.name + "在打游戏!") }; Person.prototype.eat = function() { alert(this.name + "在吃饭!") }; //创建对象p var p = new Person("小明"); //调用方法 p.playGames();
第二种:使用属性检查是否实现接口
这种方式是第一种方式的扩展,在对象的属性中声明需要实现的接口名,然后设计方式去检测该对象是否实现了指定接口,这种方式缺点很明显,并没有办法检测是否真正实现了接口中的方法。/** * 基于注释的实现-接口代码在注释中,对于程序不起任何作用,仅仅是写给程序员看。 * * 这是一个GAME接口,具备一个playGames方法 *public interface Game { * public void playGames(); * } * * * 这是一个Food接口,具备一个eat方法 * public interface Food { * public void eat(); * } */ var Person = function(name) { //通过属性的方式,声明一个属性,值为需要实现的接口名 this.implInterfaces = ["Game","Food"]; this.name = name; }; //根据注释的内容,自觉地实现接口中的方法 Person.prototype.playGames = function() { alert(this.name + "在打游戏!") }; Person.prototype.eat = function() { alert(this.name + "在吃饭!") }; //创建对象p var p = new Person("小明"); //调用方法 p.playGames(); //定义一个方法用于检测Person对象的类是否实现指定的接口 function checkPerson(person) { //调用公共的方法进行判断,如果返回false,表示没有实现接口,抛出错误 if(!checkImplements(person,"Fightable","Walkable")) throw new Error("必须实现Fightable和Walkable俩个接口"); }; //定义一个公共方法用于检测一个对象的类是否实现指定的接口 function checkImplements(obj) { //如果这个对象不具备接口属性,说明没有实现接口,抛出错误 if(!obj.implInterfaces) throw new Error("必须声明所实现的接口"); //每一个方法中都存在一个对象arguments来存储传递进来的实际参数 //arguments包含对象本身以及参数字符串,因此遍历要从下标1开始,跳过对象本身 for(var i = 1; i < arguments.length; i++) { if(typeof arguments[i] != "string") throw new Error(arguments[i] + "的类型不正确"); var found =false; for(var j = 0; j < obj.implInterfaces.length; j++) { var inter = obj.implInterfaces[j]; //检测实现的接口是否正确 if(inter == arguments[i]) { found = true; break; } } if(!found) return false; } return true; }; //检查对象p所在的类是否实现了接口 checkPerson(p);
第三种:鸭式辨型方式
鸭式辨型(这个名称来自James Whitomb Riley的名言:“像鸭子一样走路并且嘎嘎叫的就是鸭子”),意思就是说,判断一个方法是否实现了接口,只需要看这个方法中是否包含接口中的所有方法,如果包含了,我们就可以认为这个方法实现了此接口。1、首先定义一个用于创建接口的函数
//定义一个接口方法,参数为长度为2的数组,数组第一个元素为对象接口对象,第二个元素为接口方法的数组 var Interface = function(name) { //arguments为实际传进来的参数 if(arguments.length != 2) throw new Error("创建的接口不符合标准,必须有俩个参数,第二个参数是接口的方法"); this.name = name; this.methods = []; //获取方法数组 var methods = arguments[1]; for(var i = 1; i < methods.length; i++) { this.methods.push(methods[i]); } };
2、使用如上函数声明2个接口并创建对象实现接口方法
//声明俩个接口及接口的方法 var Game = new Interface("Game",["playGames"]); var Food = new Interface("Food",["eat","throwFood"]); var Person = function(name) { this.name = name; }; //实现接口的三个方法 Person.prototype.playGames = function() { alert(this.name + "在打游戏!"); }; Person.prototype.eat = function() { alert(this.name + "在吃饭!"); }; Person.prototype.throwFood = function() { alert(this.name + "丢掉食物"); }; //创建对象p var p = new Person("小明");
3、编写方法检测对象是否实现接口的方法
//用于检测对象是否实现了接口的方法,参数为数组,第一个元素为对象,其余元素为实现的接口对象 Interface.checkImplements = function(obj) { if(arguments.length < 2) throw new Error("要检查的接口必须传入接口对象的参数,参数的个数必须大于等于2"); for(var i = 1; i < arguments.length; i++) { var intObj = arguments[i]; if(intObj.constructor != Interface) throw new Error(intObj + "接口的对象不正确"); //检查方法是否符合要求 var cmethods = intObj.methods; for(var j =0; j < cmethods.length; j++) { if(!obj[cmethods[j]] || typeof obj[cmethods[j]] != "function") throw new Error("必须实现:" + cmethods[j] + "这个方法"); } } }
4、检测对象是否实现的指定接口对象中的方法
function checkPerson(person) { //调用检测方法,传入要检测的对象及其需要实现的接口对象 Interface.checkImplements(person,Game,Food); }; //检测对象p是否实现了接口 checkPerson(p);
实际使用中可以结合第一种方式一起使用
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- PropertyChangeListener简单理解
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 什么是设计模式
- 设计模式之创建型模式 - 特别的变量问题
- 七、设计模式——装饰模式
- 设计模式总结
- fastjson处理接口时的一个问题
- 设计模式之创建型模式
- 最后一次说说闭包
- Ajax
- 浅谈设计模式的学习
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块