第一章

创建一个类

方法一:
     var Anim = function() {
          ...
     };
     Anim.prototype.start = function() {
          ...
     };
     Anim.prototype.stop = function() {
          ...
     };
方法二:
     var Anim = function() {
          ...
     };
     Anim.prototype = {
          start: function() {
               ...
          },
          stop: function() {
               ...
          }
     };
方法三:
     Function.prototype.method =  function(name, fn) {
          this.prototype[name] = fn;
     };
     var Anim = function() {
          ...
     };
     Anim.method('start', function() {
          ...
     });
     Anim.method('stop', function() {
          ...
     });
方法四(在方法三上增加链式调用):
     只需要在method方法上添加return this;
     Function.prototype.method =  function(name, fn) {
          this.prototype[name] = fn;
          return this;
     };

第二章
接口模仿

方法一:用注释描述接口
/*
     interface Composite {
          function add(child);
          function remove(child);
     }
*/
 
var CompositeForm = function(id, method, action) { //inplements Composite
     ...
};
 
//继承Composite接口
 
CompositeForm.prototype.add = function(child) {
     ...
};
CompositeForm.prototype.remove = function(child) {
     ...
};
 
缺点:主要利用注释来口头约束,要靠程序员自觉遵守
优点:不需要额外的类或函数,简单方便
 

方法二:用属性检查模仿接口
说明:在方法一中增加代码,主要是在需要继承某些接口的类中添加一个属性用于,告诉别人它有没有继承某些类,此外,再增加一个检查执行的函数,就可以方便的检查某个类是否继承了某些接口
缺点: 如果程序员只是声明了自己有实现那个接口,但是没有实际实现,就会造成问题
优点: 如果程序员正真按照约定,没在代码上说谎,那么就能有效的检测是否实现了接口
例子:
/*
interface Composite {
     function add(child);
     function remove(child);
     function getChild(index);
}
 
interface FormItem() {
     function save();
}
*/
 
var CompositeForm = function(id,method,action) {
     this.implementsInterfaces = ['Composite', 'FormItem'];//类中添加了这个属性,使对象说明自己是否实现了某些类
     ...
}
 
//检查对象是否自己有声称实现了某些接口
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;
 
// 使用例子
function addForm(formInstance) {
     if(!implements(formInstance, 'Composite', 'FormItem')) {
          throw new Error("没有实现某些接口");
     }
     ...
}

方法三:鸭式辩型模仿接口
例子:
// 接口列表(个人理解:使用neInterface只是让别人知道这是一个接口定义,简单点可以直接用一个数组来代替)
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);
var FormItem = new Interface('FormItem', ['save']);
 
//使用的时候通过一个定义好的函数ensureImplements来检查是否实现了接口
ensureImplements(formInstance, Composite, FormItem);
 
说明: 这种方法的思想就是检测对象是否有与接口同名的方法
 

方法四:结合方法一和方法三的方法
例子:
// 接口列表
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);
var FormItem = new Interface('FormItem', ['save']);
 
// 要实现上述接口的类
var CompositeForm = function(id, method, action) { 
     ... // 实现Composit接口和FormItem接口
};
 
function addForm(formInstance) {
     Interface.ensureImplements(formInstance, Composite, FormItem);
}
 

Interface 类
var Interface = function(name, methods) {
     if(arguments.length != 2) {
          throw new Error("Interface constructor called with " + arguments.length + "arguments, but expected exactly 2.");
     }
     
     this.name = name;
     this.methods = [];
     for(var i = 0, len = methods.length; i< len; i++) {
          if(typeof methods[i] !== 'string') {
               throw new Error("Interface constructor expects method names to be" + "passed in as a string.");
          }
          this.methods.push(methods[i]);
     }
};
 
// 验证实现的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Interface.ensureImplements = function(object) {
    if(arguments.length < 2) {
        throw new Error("Interface.ensureImplements函数接收到的参数个数:"+arguments.length+",但是函数需要的参数个数为:2");
    }
 
    for(var i = 1, len = arguments.length; i < len; i++) {
        var interface = arguments[i];
        if(interface.constructor !== Interface) {
            throw new Error("Interface.ensureImplements函数需要参数2以及后面的参数为Interface实例")
        }
 
        for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
            var method = interface.methods[j];
            if(!object[method] || typeof object[method] !== 'function') {
                throw new Error("Interface.ensureImplements函数: 实例没有实现以下方法:"+interface.name);
            }
        }
    }
};

综合例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<html>
 
<body>
    <script>
        //Interface 类
        var Interface = function (name, methods) {
            if (arguments.length != 2) {
                throw new Error("Interface constructor called with " + arguments.length + "arguments, but expected exactly 2.");
            }
 
            this.name = name;
            this.methods = [];
            for (var i = 0, len = methods.length; i < len; i++) {
                if (typeof methods[i] !== 'string') {
                    throw new Error("Interface constructor expects method names to be" "passed in as a string.");
                }
                this.methods.push(methods[i]);
            }
        };
 
        Interface.ensureImplements = function (object) {
            if (arguments.length < 2) {
                throw new Error("Interface.ensureImplements函数接收到的参数个数:" + arguments.length + ",但是函数需要的参数个数为:2");
            }
 
            for (var i = 1, len = arguments.length; i < len; i++) {
                var interface = arguments[i];
                if (interface.constructor !== Interface) {
                    throw new Error("Interface.ensureImplements函数需要参数2以及后面的参数为Interface实例")
                }
 
                for (var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
                    var method = interface.methods[j];
                    if (!object[method] || typeof object[method] !== 'function') {
                        throw new Error("Interface.ensureImplements函数: 实例没有实现以下方法:" + interface.name);
                    }
                }
            }
        };
         
        //定义了一个接口,接口需要有run方法和jump方法
        var Animal = new Interface('Animal',['run''jump']);
         
        //实现Animal接口的Cat类
        function Cat() {}
        Cat.prototype.run = function() {};
        Cat.prototype.jump = function() {};
         
        //实现Animal接口的Dog类
        function Dog() {}
        Dog.prototype.run = function() {};
        Dog.prototype.jump = function() {};
         
        //没有实现Animal的Car类
        function Car() {}
        Car.prototype.drive = function() {};
         
        //有一只猫叫cat,有一只狗叫dog,有一部车叫car
        var cat = new Cat();
        var dog = new Dog();
        var car = new Car();
         
        //假设一个人叫啊Mark,然后他很喜欢收养动物,今天他又来收养动物了。
        var Mark = {
            adopt: function(animal) {
                Interface.ensureImplements(animal, Animal);
                console.log("收养一只"+animal.constructor.name+"成功");
            }
        };
        Mark.adopt(cat);
        Mark.adopt(dog);
        Mark.adopt(car);
         
    </script>
</body>
 
</html>
 
 
 
 
 
 
 
 
 
 
 
        

《JavaScript设计模式》笔记之第一、二章:富有表现力的JavaScript 和 接口的更多相关文章

  1. 一、富有表现力的JavaScript

    第一章:富有表现力的JavaScript 1.1  JavaScript的灵活性 1.2  弱类型语言 1.3  函数是一等对象 1.4  对象的易变性 1.5  继承 1.6  JavaScript ...

  2. 【总结】富有表现力的JavaScript

    1.JavaScript的灵活性 JavaScript是目前最流行.应用最广泛的语言之一,它是一种极富表现力的语言,它具有C家族语言所罕见的特性.这种语言允许我们使用各种方式来完成同一个任务或者功能, ...

  3. 富有表现力的javascript

    1.javascript的灵活性,你可以把它写的很简单,也可以写的很复杂,简直就是随心所欲: 2.javascript是弱类型语言,定义变量的时候不用声明变量类型,不声明类型,并不是说,javascr ...

  4. Javascript设计模式笔记

    Javascript是越来越厉害了,一统前后端开发.于是最近把设计模式又看了一遍,顺便做了个笔记,以方便自己和他人共同学习. 笔记连载详见:http://www.meteorcn.net/wordpr ...

  5. 《Linux内核设计与实现》 第一二章学习笔记

    <Linux内核设计与实现> 第一二章学习笔记 第一章 Linux内核简介 1.1 Unix的历史 Unix的特点 Unix很简洁,所提供的系统调用都有很明确的设计目的. Unix中一切皆 ...

  6. Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验

    Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高 ...

  7. [CSAPP笔记][第十二章并发编程]

    第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟 ...

  8. o'Reill的SVG精髓(第二版)学习笔记——第十二章

    第十二章 SVG动画 12.1动画基础 SVG的动画特性基于万维网联盟的“同步多媒体集成语言”(SMIL)规范(http://www.w3.org/TR/SMIL3). 在这个动画系统中,我们可以指定 ...

  9. JavaScript学习笔记(第一天)

    javascript个人笔记 JavaScript的组成 JavaScript是一种运行在客户端的脚本语言 ​ ECMAScript 标准----js的基本的语法 DOM------Document ...

随机推荐

  1. html5--3.16 button元素

    html5--3.16 button元素 学习要点 掌握button元素的使用 button元素 用来建立一个按钮从功能上来说,与input元素建立的按钮相同 button元素是双标签,其内部可以配置 ...

  2. Swing项目编译成exe,并且打包成安装文件(一)

    我们一般用java做Swing项目的时候一般都是只能在Myeclipse里面运行,那么怎么把我们的项目打包成exe可以直接双击运行呢? 初始工作:为了不让用户安装java环境,所以我们先新建一个文件夹 ...

  3. linux应用之perl环境的安装(centos)

    1.安装Perl环境 yum install perl*这个命令基本上把perl的模块给安装齐了.yum install cpanCPAN这个就不用说了吧,大家都懂. 如果你对perl模块版本要求比较 ...

  4. hdu 1753 大明A+B(大数)

    题意:小数大数加法 思路:大数模板 #include<iostream> #include<stdio.h> #include<string.h> using na ...

  5. bootstrap 学习笔记(5)---- 图片和响应式工具

    (一)响应式图片: 在 Bootstrap 版本 3 中,通过为图片添加 .img-responsive 类可以让图片支持响应式布局.其实质是为图片设置了 max-width: 100%;. heig ...

  6. 如何理解Web应用程序的MVC模型?

    View,也就是视图/视野,是你真正看到的,而非想象中的 Model.Controller,也就是控制器,是你用来改变 Model 方式.简单的说 Controller 和 View 分别是 Mode ...

  7. Android Studio工程Gradle编译报错

    一.环境的搭建: 首先搭建好AndroidStudio环境.我使用的是Ubuntu 12.04系统(由于此机器还要运行其他程序,为避免兼容性问题,暂未更新到最新,而继续沿用此稳定版),java和jdk ...

  8. EF之贪婪加载和延迟加载

    这篇文章将讨论查询结果的控制 在使用EF(Entity Framework)的过程中,很多时候我们会进行查询的操作,因此知道哪些数据会被加载到内存当中就至关重要.在多多的情况下,你可能并并不需要加载全 ...

  9. 基于微信的SDK的学习与使用——实现产品支付

    声明本篇博客为作者原创,本篇是继支付宝支付之后本人又学习的第二种支付实现,本篇着重于原理与注意事项的学习. 参考  参考 微信支付的开发文档相比支付宝的比较简单,但是使用功能丝毫也不含糊,我觉得简单易 ...

  10. C# 外界调用方法是 方法名是string类型的解决方法