1. /*
  2. 接口:提供一种说明一个对象应该有哪些方法的手段
  3. js中有三种方式实现接口:
  4. 1 注释描述接口
  5. 2 属性检测接口
  6. 3 鸭式辨型接口
  7. */
  8.  
  9. /*
  10. 1 注释描述接口: 不推荐
  11. 优点: 利用注解,给出参考
  12. 缺点:纯文档约束,是一个假接口,
  13. 程序不能检查实现接口对象是否实现所有接口方法
  14. */
  15.  
  16. /**
  17. * interface Composite{
  18. * function a();
  19. * function b();
  20. * }
  21. */
  22. // CompositeImpl implements Composite
  23. var CompositeImpl = function(){
  24. //业务逻辑
  25. };
  26. CompositeImpl.prototype.a = function(){
  27. //业务逻辑
  28. };
  29. CompositeImpl.prototype.b = function(){
  30. //业务逻辑
  31. };
  32.  
  33. /*
  34. 2 属性检测接口:
  35. 优点:能够检测实现哪些接口
  36. 缺点:没有完全脱离文档,
  37. 不能检测是否实现每个接口里的所有方法
  38. */
  39. /**
  40. * interface Composite{
  41. * function a();
  42. * }
  43. *
  44. * interface FormItem(){
  45. * function b();
  46. * }
  47. */
  48. // CompositeImpl implements Composite,FormItem
  49. var interfacesImpl = function(){
  50. //在实现类内部用一个数组保存要实现的方法名
  51. //通常这个属性名是团队中规定好的
  52. this.implementsInterfaces = ["Composite","FormItem"];
  53. };
  54. CompositeImpl.prototype.a = function(){
  55. //业务逻辑
  56. };
  57. CompositeImpl.prototype.b = function(){
  58. //业务逻辑
  59. };
  60.  
  61. //专门为这个实现对象写一个检测函数,传入实例对象,用于检查实力对象是否实现了所有接口
  62. function checkImplements(obj){
  63. //调用检查方法 obj是否实现两个接口,如果没有都实现则抛出异常
  64. if(!isImplements(obj,"Composite","FormItem")){
  65. throw new Error("接口没有全部实现!");
  66. }
  67. //接收一个参数obj是要检查的对象
  68. function isImplements(obj){
  69. //arguments对象能够获取实际传入函数的所有参数的数组
  70. //传入的第0个参数是要检查的对象,所以从1开始检查
  71. for(var i = 1; i < arguments.length ; i++){
  72. //接收接口中每个接口的名字
  73. var interfaceName = arguments[i];
  74. //一个标记,是否实现这个接口,默认没有
  75. var foundFlag = false;
  76. //循环查询传入实例对象的实现接口数组 以检查是否全部实现
  77. for(var j = 0 ;j <obj.implementsInterfaces.length;j++){
  78. //如果 实现了这个接口 就修改标记跳出循环
  79. if(obj.implementsInterfaces[j]==interfaceName){
  80. foundFlag = true;
  81. break;
  82. }
  83. }
  84. //如果遍历实现接口数组之后没找到 就返回false
  85. if(!foundFlag){
  86. return false;
  87. }
  88. }
  89. //如果都找到了 返回true
  90. return true;
  91. }
  92. }
  93.  
  94. //使用实力对象并检测
  95. var o = new interfacesImpl();
  96. checkImplements(o); //不会抛出异常 因为正确实现了两个接口
  97. //如果在写interfacesImpl内的implementsInterfaces列表的时候少写了,那么就会在检查函数中抛出异常
  98.  
  99. /*
  100. 3 鸭式辨型法:(目前开发中使用的方式)
  101. 实现思想:
  102.  
  103. */
  104.  
  105. //1 接口类 Class Interface
  106. /**
  107. * 接口类需要的参数:
  108. * 1 接口的名字
  109. * 2 要实现方法名称的数组
  110. */
  111. var Interface = function( name , methods ){
  112. //判断参数个数
  113. if(arguments.length!=2){
  114. throw new Error("接口构造器参数必须是两个!");
  115. }
  116. this.name = name;
  117. this.methods = [];
  118. for(var i = 0;i<methods.length;i++){
  119. if( typeof methods[i] !== "string" ){
  120. throw new Error("接口实现的函数名称必须是字符串!");
  121. }
  122. this.methods.push(methods[i]);
  123. }
  124.  
  125. };
  126. //2 准备工作:
  127. // 2.1 实例化接口对象 传入接口名 和 要实现的方法数组
  128. var CompositeInterface = new Interface("CompositeInterface",["add","remove"]);
  129. var FormItemInterface = new Interface("FormItemInterface",["update","select"]);
  130.  
  131. // 2.2 实现接口的类
  132. //CompositeImpl implementes CompositeInterface ,FormItemInterface
  133. var CompositeImpl = function(){
  134.  
  135. };
  136. // 2.3 实现接口的方法
  137. CompositeImpl.prototype.add = function(obj){
  138. alert("add...");
  139. };
  140. CompositeImpl.prototype.remove = function(obj){
  141. alert("remove...");
  142. };
  143. CompositeImpl.prototype.select = function(obj){
  144. alert("select...");
  145. };
  146. //在这里少实现一个方法 下面检测是否全部实现了接口方法
  147. // CompositeImpl.prototype.update = function(obj){
  148. // alert("update...");
  149. // };
  150. // 实例化 实现接口的对象
  151. var c = new CompositeImpl();
  152.  
  153. //3 检验接口里的方法是否全部实现
  154. // 如果检验通过 继续执行;如果不通过抛出异常;
  155. Interface.ensureImplements = function(obj){
  156. // 如果接收到参数小于2 说明 传参出错了,只传入一个参数,,没有传入实现的接口
  157. if(arguments.length<2){
  158. throw new Error("接口检查方法的参数必须多余两个!");
  159. }
  160. //获得要见测的接口实现对象之后的参数 各个接口
  161. for(var i = 1,len = arguments.length;i<len;i++){
  162. var instanceInterface = arguments[i]; //获取当前这个接口
  163. //判断接收到的是不是接口的对象 如果不是 抛出异常
  164. if( instanceInterface.constructor !== Interface){
  165. throw new Error("接口检测函数必须传入接口对象!");
  166. }
  167. //检查实例化接口的对象是不是实现了接口里的所有方法
  168. // 当前接口对象里的每一个方法
  169. for(var j = 0 ; j<instanceInterface.methods.length;j++){
  170. var methodName = instanceInterface.methods[j]; //接收到了字符串的方法名
  171. //如果obj里面没有有methodName这个方法 或者有这个属性但是不是函数 就抛出异常
  172. if(!obj[methodName] || typeof obj[methodName] !== "function"){
  173. throw new Error("接口方法"+ methodName +"没有实现!");
  174. }
  175. }
  176. }
  177.  
  178. };
  179. //传入要检查的类,和他要实现的所有接口对象
  180. Interface.ensureImplements(c ,CompositeInterface ,FormItemInterface );
  181. c.add();

JavaScript实现接口的三种经典方式的更多相关文章

  1. C#接口的三种实现方式

    转自原文C#接口的三种实现方式 public interface MyInterface { /// 下面三个方法的签名都是 /// .method public hidebysig newslot ...

  2. 初见Ajax——javascript访问DOM的三种访问方式

    最近好啰嗦 最近在一间小公司实习,写一些小东西.小公司嘛,人们都说在小公司要什么都写的.果真是. 前端,后台,无论是HTML,CSS,JavaScript还是XML,Java,都要自己全包了.还好前台 ...

  3. JavaScript声明全局变量的三种方式

    JavaScript声明全局变量的三种方式   JS中声明全局变量主要分为显式声明或者隐式声明下面分别介绍. 声明方式一: 使用var(关键字)+变量名(标识符)的方式在function外部声明,即为 ...

  4. 【转】SVG与HTML、JavaScript的三种调用方式

    原文:https://www.cnblogs.com/guohu/p/5085045.html SVG与HTML.JavaScript的三种调用方式 一.在HTMl中访问SVG的DOM 1 2 3 4 ...

  5. JavaScript 闭包的详细分享(三种创建方式)(附小实例)

    JavaScript闭包的详细理解 一.原理:闭包函数--指有权访问私有函数里面的变量和对象还有方法等:通俗的讲就是突破私有函数的作用域,让函数外面能够使用函数里面的变量及方法. 1.第一种创建方式 ...

  6. javascript中构造函数的三种方式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. JavaScript中创建对象的三种方式!

    JavaScript中创建对象的三种方式! 第一种 利用对象字面量! // 创建对象的三种方式! // 1 对象字面量. var obj = { // 对象的属性和方法! name: 'lvhang' ...

  8. JavaScript新手学习笔记3——三种排序方式(冒泡排序、插入排序、快速排序)

    每种编程语言学到数组的时候,都会讲到排序算法,当时学C语言的时候,卡在排序算法.今天来总结一下javascript中如何实现三种排序算法. 1.冒泡排序(默认升序排列哦) 原理: 冒泡排序的原理,顾名 ...

  9. python笔记-20 django进阶 (model与form、modelform对比,三种ajax方式的对比,随机验证码,kindeditor)

    一.model深入 1.model的功能 1.1 创建数据库表 1.2 操作数据库表 1.3 数据库的增删改查操作 2.创建数据库表的单表操作 2.1 定义表对象 class xxx(models.M ...

随机推荐

  1. linux PMBus总线及设备驱动分析

    PMBus协议规范介绍 PMBus是一套对电源进行配置.控制和监控的通讯协议标准.其最新版本为1.3,该规范还在不断演进中,比如新标准中新增的zone PMBus.AVSBus等特性.在其官网上有详细 ...

  2. 重读 必须知道的.NET

    1 .public ,对访问成员无限制,属于访问级别最高的权限. protected 访问包含类或者丛类派生类的类. internal  仅限于程序集, protected inernal 访问仅限于 ...

  3. Eclipse项目出现红色叹号的解决办法

    以前的项目今天打开突然出现了红色的叹号,对于强迫症的患者简直忍不了,出现红色叹号的原因都是jar包出现问题导致的,如果是代码错误早就是一个大红叉了- 打开项目就可以发现,找不到哪里出问题了,代码和js ...

  4. JQ在光标处插入文字

    内容转载自网络这是一个JQ的扩展方法.在teatarea获得焦点时,往光标处插入文字,扩展代码如下 (function($){ $.fn.extend({ "insert":fun ...

  5. Mysql语句的执行过程

    当你希望MySQL能够以更高的性能运行查询时,最好的办法是弄清楚MySQL是如何优化和执行查询.<高性能MySQL> MySQL客户端与服务器端的通信特点 客户端与服务器之间是半双工通信, ...

  6. 笔记:Jersey REST 传输格式

    通常REST接口会以XML或JSON作为主要传输格式,同时 Jersey 也支持其他的数据格式,比如基本类型.文件.流等格式. 基本类型 Java的基本类型又叫原生类型,包括4种整数(byte.sho ...

  7. SpringBoot 整合 Swagger2

    1. Swagger UI 按以下步骤配置,项目启动后访问:http://localhost:8080/swagger-ui.html 1.1 添加依赖 <dependency> < ...

  8. MyBatis-plus 代码生成器

    1.添加pom文件依赖 <!-- Mybatis-Plus 自动生成实体类--> <dependency> <groupId>com.baomidou</gr ...

  9. Oracle查询优化改写--------------------范围处理

    一.定位连续值的范围 二.查找同一组或分区中行之间的差

  10. java并发编程基础 --- 7章节 java中的13个原子操作类

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量 i=1,A线程更新 i+1,B线程也更新 I+1,经过两个线程的操作之后可能 I不等于3,而是等于2.因为A和B线程更 ...