JavaScript-设计模式之接口的实现

来源:互联网 发布:编程笔记本电脑 编辑:程序博客网 时间:2024/05/23 21:16

在JS中,并没有真正意义上的接口,我们只能通过模拟的方式实现接口的效果,使用接口可以促进代码的重用,降低代码之间的耦合度,减少代码错误及查找错误原因,坏处就是加大代码量,而且并不能强制程序员实现接口。JS中模拟接口的方式有三种。


第一种:注释的方式

这种方式是使用注释显示的告诉程序员需要实现哪些接口,这种方式完全靠程序员的自觉性,并且是否真正实现了接口并不能检查,对代码的调试不起任何帮助,相反正因为这种方式,不会对代码性能产生影响。

 /**  * 基于注释的实现-接口代码在注释中,对于程序不起任何作用,仅仅是写给程序员看。  *  * 这是一个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);

实际使用中可以结合第一种方式一起使用

0 1
原创粉丝点击