接口

在JavaScrip中模仿接口

用注释描述接口

/*

interface Composite {
    function add(child);
    function remove(child);
    function getChild(index);
}

interface FormItem {
    function save();
}

*/

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

Composite.prototype.add = function(child) {
    console.log("add");
}

Composite.prototype.remove = function(child) {
    console.log("remove");
}

Composite.prototype.getChild = function(index) {
    console.log("getChild");
}

Composite.prototype.save = function() {
    console.log("save");
};

var instance = new Composite(1, 2, 3);
instance.add();
instance.remove();
instance.getChild();
instance.save();

用属性检查模仿接口

概括:

  • 一个方法用于表明自己实现了哪些接口。
  • 一个方法用于验证是否实现了所有的接口,如果没有,则抛出异常。
  • 一个方法用于判断某个类是否实现了所有的接口。

缺点:

  • 自己说自己实现了什么接口,但是可能自己并没有实现,但是代码却不会抛出异常。
  • 用了两层for循环,会引起性能消耗。
/*

interface Composite {
    function add(child);
    function remove(child);
    function getChild(index);
}

interface FormItem {
    function save();
}

*/

var CompositeForm = function(id, method, action) {
    this.implementsInterface = ['Composite', 'FormItem'];
    // ...
} 

function addForm(instance) {
    if(!implements(instance, 'Composite', 'FormItem')) {
        throw new Error('Object does not implement a required interface');
    }

    if(!implements(instance, 'test', 'FormItem')) {
        throw new Error('Object does not implement a required 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.implementsInterface.length;j++) {
            if(object.implementsInterface[j] == interfaceName) {
                interfaceFound = true;
                break;
            }
        }
        if(!interfaceFound) {
            return false;
        }
    }
    return true;
} 

var instance = new CompositeForm(1, 2, 3);
addForm(instance);

用鸭式辨型模仿接口

  • 类是否声明自己支持哪些接口并不重要, 只要具有这些接口中的方法就可以了。
  • 它把对象实现的方法集作为判断它是不是某个类的实例的唯一标准。
  • 也就是说,如果对象具有与接口定义的方法同名的所有方法,那么就可以认为它实现了这个接口。
// Interface.js文件

/*
 * 一个接口
 * @param {string} name 接口的名字
 * @param {array} methods 接口要实现的方法
 * @class
 */
var Interface = function(name, methods) {
    if(arguments.length !== 2) {
        throw new Error("Interface constructor called with " + arguments.length
            + "arguments, but expectly exactly 2.");
    }

    this.name = name;
    this.methods = [];

    for(var i = 1;i < methods.length;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]);
    }
};

/*
 * static class method 用于实现检测对象是否实现了接口里的所有方法
 *
 * @param {object} object 它应该包含一个对象的实例和至少一个接口
 *
 */

Interface.prototype.ensureImplements = function(object) {
    if(arguments.length < 2) {
        throw new Error("Function Interface.ensureImplements called with " + arguments.length
            + "arguments, but expectly at least 2.");
    }

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

        if(interface.constructor !== Interface) {
            throw new Error("Function interface.ensureImplements expects arguments "
                + "two and above to be instances of 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("Function Interface.ensureImplements: Object "
                    + "does not implement the " + interface.name
                    + " interface.Method " + method + " was not found");
            }
        }
    }
}

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <script src="Interface.js"></script>
    <script type="text/javascript">

        // 实例化一个接口
        var PeopleInterface = new Interface('PeopleInterface', ['run', 'eat']);

        // 封装一个People类
        var People = function(name) {
            this.name = name;
        };

        People.prototype.run = function() {
            console.log(this.name + " is running...");
        };

        People.prototype.eat = function() {
            console.log(this.name + " is eating...");
        };

        // 实例化一个People对象
        var yzf = new People('yzf');

        function addPeople(instance) {

            // 对yzf进行检测,看它是否完全继承了PeopleInterface接口
            PeopleInterface.ensureImplements(yzf, PeopleInterface);

            // 如果没有抛出异常,就可以使用下面这些方法了
            yzf.run();
            yzf.eat();
        }

        addPeople(yzf);
    </script>
</body>
</html>

依赖于接口的设计模式

工厂模式

组合模式

装饰者模式

命令模式

JavaScript设计模式读书笔记之一:接口的更多相关文章

  1. JavaScript设计模式:读书笔记(未完)

    该篇随我读书的进度持续更新阅读书目:<JavaScript设计模式> 2016/3/30 2016/3/31 2016/4/8 2016/3/30: 模式是一种可复用的解决方案,可用于解决 ...

  2. JavaScript设计模式 -- 读书笔记

    JavaScript设计模式 一. 设计模式 一个模式就是一个可重用的方案: 有效的解决方法.易重用.善于表达该解决方案: 未通过"模式特性"测试的模式称为模式原型: 三规则:适用 ...

  3. 《你不知道的javascript》读书笔记2

    概述 放假读完了<你不知道的javascript>上篇,学到了很多东西,记录下来,供以后开发时参考,相信对其他人也有用. 这篇笔记是这本书的下半部分,上半部分请见<你不知道的java ...

  4. HeadFirst设计模式读书笔记--目录

    HeadFirst设计模式读书笔记(1)-策略模式(Strategy Pattern) HeadFirst设计模式读书笔记(2)-观察者模式(Observer Pattern) HeadFirst设计 ...

  5. 《编写可维护的javascript》读书笔记(中)——编程实践

    上篇读书笔记系列之:<编写可维护的javascript>读书笔记(上) 上篇说的是编程风格,记录的都是最重要的点,不讲废话,写的比较简洁,而本篇将加入一些实例,因为那样比较容易说明问题. ...

  6. JavaScript设计模式学习笔记

    1 JavaScript设计模式深入分析 私有属性和方法:函数有作用域,在函数内用var 关键字声明的变量在外部无法访问,私有属性和方法本质就是你希望在对象外部无法访问的变量. 特权属性和方法:创建属 ...

  7. Javascript & JQuery读书笔记

    Hi All, 分享一下我学JS & JQuery的读书笔记: JS的3个不足:复杂的文档对象模型(DOM),不一致的浏览器的实现和便捷的开发,调试工具的缺乏. Jquery的选择器 a. 基 ...

  8. Head First 设计模式读书笔记(1)-策略模式

    一.策略模式的定义 策略模式定义了算法族,分别封装起来,让它们之间可以互换替换,此模式让算法的变化独立使用算法的客户. 二.使用策略模式的一个例子 2.1引出问题 某公司做了一套模拟鸭子的游戏:该游戏 ...

  9. JavaScript设计模式系列学习笔记目录

    说明 本系列笔记参考书籍<JavaScript设计模式>.<JavaScript高级程序设计3> 参考博客:汤姆大叔博客:http://www.cnblogs.com/TomX ...

随机推荐

  1. Java集合框架之三:HashMap源码解析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! HashMap在我们的工作中应用的非常广泛,在工作面试中也经常会被问到,对于这样一个重要的集合模型我们有必要弄清楚它的使用方法和它底层的实 ...

  2. 2017-2-19 C#基础 基本数据类型的转换,转义字符,常量

    1.基本数据类型的转换分两种:自动转换(隐式转换)和强制转换(显式转换).自动转换是从只类型转换到引用类型.强制转换是最长用的,是从引用类型转换到值类型或者从浮点型转换到整形.强制转换主要有三种形式: ...

  3. SuperWebClient -一个基于CURL的.NET HTTP/HTTPS模拟神组件(2)

    今天我们讨论SuperWebClient组件使用中的几个简单主题 1: UserAgent2: Cookies3: POST登录 1:UserAgent这个是客户端标识信息,此信息是用于鉴别正在访问W ...

  4. 蔡勒(Zeller)公式:根据日期推算是星期几

    Zeller's Congruence: w=y + [y/4] + [c/4] - 2c + [26(m+1)/10] + d - 1 公式中的符号含义如下:w:星期: w对7取模得:0-星期日,1 ...

  5. linux 下maven安装

    版本要求maven3.2.3 软件下载 wget http://mirror.bit.edu.cn/apache/maven/maven-3/3.2.3/binaries/apache-maven-3 ...

  6. Linux TCP连接数修改

    一.           文件数限制修改 (1)   vi /etc/security/limits.conf *  soft nofile 10240    *  hard nofile 10240 ...

  7. (三目运算符)PHP中问号?和冒号: 的作用

    <表达式1>?<表达式2>:<表达式3>; "?"运算符的含义是: 先求表达式1的值, 如果为真, 则执行表达式2,并返回表达式2的结果 ; 如 ...

  8. FineUIMvc随笔 - 不能忘却的回发(__doPostBack)

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 用户反馈 有网友在官方论坛抛出了这么一个问题,似乎对 FineUIMvc 中的浏览器端与服务器端的交互方式很有异议. 这里面的关 ...

  9. 强化学习读书笔记 - 05 - 蒙特卡洛方法(Monte Carlo Methods)

    强化学习读书笔记 - 05 - 蒙特卡洛方法(Monte Carlo Methods) 学习笔记: Reinforcement Learning: An Introduction, Richard S ...

  10. 【UWP】Gank 干货集中营 客户端

    简介 一个偶然的机会,在网上看到了 <「代码家」的学习过程和学习经验分享>,知道了代码家做的Gank网站. 干货集中营 每日分享妹子图 和 技术干货,还有供大家中午休息的休闲视频 在看过一 ...