zoukankan      html  css  js  c++  java
  • Javascript设计模式读书笔记二 接口

    Javascript 接口;设计模式的经典语录“针对接口而不是类编程”

    Javascript是种弱类型语言,类型不匹配错误很难跟踪,使用接口可以让这种错误的查找变得更容易点;接口还可以让逻辑代码变得更稳固,因为接口添加一个操作,类必须实现它。

    Javascript接口缺点:在某种程序上增加额外方法调用的开销(可以在开发完成后剔除接口代码);Javascript接口必须用手工的办法保证某个类实现某个接口,编码规范和辅助类可以提供一些帮助,但无法彻底根除这个问题,除非项目组的人员都同意并且强制使用接口并对其检查,否则接口很多价值都无法体现。

    1、  在Javascript中模仿接口。使用注释来模仿其它语言的接口做法。代码如下:

    /*

      interface Composite{

           function add(child);

        function remove(child);

        function getChild(index);

    }

    interface FormItem{

           function save();

    }

    */

    上面的一段注释即为模仿接口,只是人为按照这种方式来实现这种接口。程序并不会真正继承,程序也不会检查错误。实现接口代码如下:

    var CompositeForm=function(id,method,action){  //implements Composite,FormItem

       …

    };

    //实现Composite接口

    CompositeForm.prototype.add=function(child){

       …

    };

    CompositeForm.prototype.remove=function(child){

       …

    };

    CompositeForm.prototype.getChild=function(index){

       …

    };

    //实现FormItem接口

    CompositeForm.prototype.save=function(){

       …

    };

    尽管以上如此,只是人为的模仿,但也有其优点。不需要额外的类或函数。可以提高代码的可重用性,因为现在那些类实现的接口都有说明。缺点就是不会提供错误消息,对测试和调试没有帮助。

    2、 用属性检查模仿接口。

     这一种方法要更严谨一点。但仍然只是注释,但现在可以通过检查一个属性得知某个类自称实现了什么接口。代码如下:

    /*

      interface Composite{

           function add(child);

        function remove(child);

        function getChild(index);

    }

    interface FormItem{

           function save();

    }

    */

    var CompositeForm=function(id,method,action){  //implements Composite,FormItem

       this.implementsInterfaces=[‘Composite’,’FormItem’];

    };

    //实现Composite接口

    CompositeForm.prototype.add=function(child){

       …

    };

    CompositeForm.prototype.remove=function(child){

       …

    };

    CompositeForm.prototype.getChild=function(index){

       …

    };

    //实现FormItem接口

    CompositeForm.prototype.save=function(){

       …

    };

    function addForm(formInstance){

       If(!implements(formInstance,’Composite’,’FormItem’)){

                  Throw new Error(“Object does not implement a require interface”);

    }

    }

    function implements(object){

       for(var i=1;i<arguments.length;i++){

                  var interfaceName=arguments[i];

        var interfaceFound=false;

       for(var j=0;j<object.implementsInterfaces.length;j++){

              if(object.implementsInterfaces[j]==interfaceName){

              interfaceFound=true;

       break;

    }

    }

    if(!interfaceFound){

              return false;

    }

    }

    Return true;

    }

         以上这种方法只是模仿接口的改进。可以检查是否实现某个接口,但并不真正的实现。

    3、 用鸭式辨型模仿接口。

    其实,类是否声明自己支持那些接口并不重要,只要它具有这些接口中的方法就行。把对象实现的方法集作为判断它是不是某个类的实例的唯一标准。这种技术在检查一个类是否实现了某个接口时也大显身手。这就是鸭式辨型模仿接口。可以用一个辅助函数来确保对象具有所有必需的方法。代码如下:

    //接口.

    var Composite=new Interface(‘Composite’,[‘add’,’remove’,’getChild’]);

    var FormItem=new Interface(‘FormItem’,[‘save’]);

    //实现类

    var CompositeForm=function(id,method,action){         …

    };

      ……

      Function addForm(formInstance){

            ensureImplements(formInstance,Composite,FormItem);

        //如果没有实现某个方法这个函数将会抛出一个错误

    }

    ensureImplements函数至少需要两个参数,每一个是想要检查的对象,其余参数是据以对那个对象进行检查的接口。这种方法需要一个辅助类Interface和一个辅助函数ensureImplements。而且它只关心方法的名称,并不检查其参数的名称、数目或类型。些方式是上述三种方法中最有用的一种。

    在现实中,我们可以综合使用第一和第三种方法。即可以提高代码的可重用性及其文档的完善,又可以用辅助类和方法来对对象实现的方法进行显式检查。

    Interface 定义代码如下:

    var Interface = function (name, methods) {       

    if (arguments.length != 2) {           

    throw new Error("the interface length is bigger than 2");       

    }       

    this.Name = name;       

    this.Method = [];       

    for (var i = 0; i < methods.length; i++) {       

    if(typeof methods[i]!== string) {       

    throw new Error("the method name is not string");       

    }       

    this.Method.push(methods[i]);       

    }   

    }   

    /* ensureImplement 方法实现*/   

    Interface.ensureImplement = function (object) {       

    if (arguments.length < 2) {           

    throw new Error("there is not Interface or the instance");       

    }       

    for (var i = 1; i < arguments.length; i++) {           

    var interface1 = arguments[i];           

    if (interface1.constructor !== Interface) {               

    throw new Error("the argument is not interface");           

     }           

    for (var j = 0; j < interface1.Method.length; j++) {               

    var method = interface1.Method[j];               

    if (!object[method] || typeof object[method] !== function) {                   

     throw new Error("you instance doesnt implement the interface");                                  

    }           

    }       

    }   

    }

    使用示例:

    var DynamicMap=new Interface(‘DynamicMap’,[‘centerOnPoint’,’zoom’,’draw’]);

    function displayRoute(mapInstance){

      Interface.ensureImplements(mapInstance,DynamicMap);

       mapInstance.centerOnPoint(12,34);

       mapInstance.zoom(5);

       mapInstance.draw();

       …

    }

    下面这段代码简要的说明了其使用:

    var Person = new Interface("Person", ["GetName", "GetAge"]);     

    var Man = function (name, age) {       

    this.Name = name;       

    this.Age = age;   

    }   

    Man.prototype = {

    GetName: function () { return this.Name; },      // 

    GetAge: function () { return this.Age; }   

    }   

    var test = function (instance) {              

    Interface.ensureImplement(instance, Person);          

    var name = instance.GetName();       

    alert(name);   

    }   

    test(new Man("Alan",20));
    如果我们注释了上面的GetAge方法,在执行的时候就会出错。在ensureImplement的时候发现并没有去实现这个方法。

    4、  设计模式中依赖于接口的主要有以下这些。

    工厂模式

    组合模式

    装饰者模式

    命令模式

    会在以后的章节中介绍。

    完成于2013-01-17  20:54

  • 相关阅读:
    go语言最新版本 下载地址
    PHP5 各版本维护时间
    springzuul本地路由和跨服务器路由问题
    大数据学习路线(转载)
    springcoud feign超时的问题
    java 桥接模式
    springcloud单个服务内存使用详情
    centos7搭建filebeat
    centos7搭建logstash
    centos7搭建kibana
  • 原文地址:https://www.cnblogs.com/webdep/p/2865197.html
Copyright © 2011-2022 走看看