内容简介
本书是根据Javascript语言的特专门针对Javascript语言结的设计模式。全书共分为三个部分,第 一部分讲解了Javascript语言面向对象和函数式编程的知识及其在设计模式方面的作用;第 二部分通过一步步完善的代码示例,由浅入深地讲解了16个设计模式;第三部分讲述了面向对象的设计原则及其在设计模式中的体现,以及一些常见的面向对象编程技巧和日常开发中的代码重构。 书中所有示例均来自作者的开发实践,与实际开发密切相关,适合初、中、高 级Web前端开发人员阅读,尤其适合想往架构师晋级的中高 级程序员。
目录
目录第 一部分 基础知识第 1章 面向对象的Javascript 21.1 动态类型语言和鸭子类型 21.2 多态 41.2.1 一段“多态”的Javascript代码 51.2.2 对象的多态 51.2.3 类型检查和多态 61.2.4 使用继承得到多态效果 71.2.5 Javascript的多态 81.2.6 多态在面向对象程序设计中的作用 91.2.7 设计模式与多态 111.3 封装 121.3.1 封装数据 121.3.2 封装实现 121.3.3 封装类型 131.3.4 封装变化 131.4 原型模式和基于原型继承的Javascript对象系统 141.4.1 使用克隆的原型模式 141.4.2 克隆是创建对象的手段 151.4.3 体验Io语言 151.4.4 原型编程范型的一些规则 171.4.5 Javascript中的原型继承 181.4.6 原型继承的未来 221.4.6 小结 23第 2章 this、call和apply 242.1 this 242.1.1 this的指向 242.1.2 丢失的this 272.2 call和apply 292.2.1 call和apply的区别 292.2.2 call和apply的用途 30第3章 和高阶函数 353.1 353.1.1 变量的作用域 353.1.2 变量的生存周期 363.1.3 的更多作用 383.1.4 和面向对象设计 403.1.5 用实现命令模式 413.1.6 与内存管理 433.2 高阶函数 443.2.1 函数作为参数传递 443.2.2 函数作为返回值输出 463.2.3 高阶函数实现AOP 473.2.4 高阶函数的其他应用 493.3 小结 58第 二部分 设计模式第4章 单例模式 604.1 实现单例模式 604.2 透明的单例模式 614.3 用代理实现单例模式 624.4 Javascript中的单例模式 634.5 惰单例 654.6 通用的惰单例 684.7 小结 70第5章 程序员与算法 715.1 使用策略模式计算奖金 725.2 Javascript版本的策略模式 755.3 多态在策略模式中的体现 765.4 使用策略模式实现缓动动画 765.4.1 实现动画效果的原理 765.4.2 思路和一些准备工作 775.4.3 让小球运动起来 775.5 更广义的“算法” 805.6 表单校验 805.6.1 表单校验的第 一个版本 805.6.2 用策略模式重构表单校验 815.6.3 给某个文本输入框添加多种校验规则 835.7 策略模式的优缺点 865.8 一等函数对象与策略模式 865.9 小结 87第6章 代理模式 886.1 第 一个例子——小明追MM的故事 886.2 保护代理和虚拟代理 916.3 虚拟代理实现图片预加载 916.4 代理的意义 936.5 代理和本体接口的一致 946.6 虚拟代理合并请求 956.7 虚拟代理在惰加载中的应用 976.8 缓存代理 996.8.1 缓存代理的例子——计算乘积 996.8.2 缓存代理用于ajax异步请求数据 1006.9 用高阶函数动态创建代理 1006.10 其他代理模式 1016.11 小结 102第7章 迭代器模式 1037.1 jQuery中的迭代器 1037.2 实现自己的迭代器 1047.3 内部迭代器和外部迭代器 1047.4 迭代类数组对象和字面量对象 1067.5 倒序迭代器 1067.6 中止迭代器 1077.7 迭代器模式的应用举例 1077.8 小结 109第8章 发布—订阅模式 1108.1 现实中的发布—订阅模式 1108.2 发布—订阅模式的作用 1108.3 DOM事件 1118.4 自定义事件 1128.5 发布—订阅模式的通用实现 1138.6 取消订阅的事件 1158.7 真实的例子——网站登录 1158.8 全局的发布—订阅对象 1178.9 模块间通信 1198.10 必须先订阅再发布吗 1208.11 全局事件的命名冲突 1218.12 Javascript实现发布—订阅模式的便利 1248.13 小结 124第9章 命令模式 1259.1 命令模式的用途 1259.2 命令模式的例子——菜单程序 1269.3 Javascript中的命令模式 1289.4 撤销命令 1309.5 恢复命令日志 1329.6 命令队列 1339.7 宏命令 1349.8 智能命令与傻瓜命令 1359.9 小结 136第 10章 组合模式 13710.1 回顾宏命令 13810.2 组合模式的用途 13910.3 请求在树中传递的过程 13910.4 更强大的宏命令 14010.5 抽象类在组合模式中的作用 14310.6 透明带来的问题 14410.7 组合模式的例子——扫描文件夹 14510.8 一些值得注意的地方 14710.9 引用父对象 14810.10 何时使用组合模式 15010.11 小结 150第 11章 模板方法模式 15111.1 模板方法模式的定义和组成 15111.2 第 一个例子Coffee or Tea 15111.2.1 先泡一杯咖啡 15211.2.2 沏一壶茶 15211.2.3 分离出共同点 15311.2.4 创建Coffee子类和Tea子类 15411.3 抽象类 15611.3.1 抽象类的作用 15611.3.2 抽象方法和具体方法 15611.3.3 用Java实现Coffee or Tea的例子 15711.3.4 Javascript没有抽象类的缺点和变通 15811.4 模板方法模式的使用场景 15911.5 钩子方法 16011.6 好莱坞原则 16211.7 真的需要“继承”吗 16211.8 小结 164第 12章 享元模式 16512.1 初识享元模式 16512.2 内部状态与外部状态 16612.3 享元模式的通用结构 16712.4 文件上传的例子 16712.4.1 对象爆炸 16812.4.2 享元模式重构文件上传 17012.4.3 剥离外部状态 17012.4.4 工行对象实例化 17112.4.5 管理器封装外部状态 17112.5 享元模式的适用 17312.6 再谈内部状态和外部状态 17312.6.1 没有内部状态的享元 17312.6.2 没有外部状态的“享元” 17412.7 对象池 17512.7.1 对象池实现 17512.7.2 通用对象池实现 17712.8 小结 178第 13章 职责链模式 17913.1 现实中的职责链模式 17913.2 实际开发中的职责链模式 18013.3 用职责链模式重构代码 18113.4 灵活可拆分的职责链节点 18313.5 异步的职责链 18413.6 职责链模式的优缺点 18513.7 用AOP实现职责链 18613.8 用职责链模式获取文件上传对象 18713.9 小结 188第 14章 中介者模式 18914.1 现实中的中介者 19014.2 中介者模式的例子——泡泡堂游戏 19114.2.1 为游戏增加队伍 19214.2.2 玩家增多带来的困扰 19414.2.3 用中介者模式改造泡泡堂游戏 19414.3 中介者模式的例子——购买商品 19914.3.1 开始编写代码 20114.3.2 对象之间的联系 20214.3.3 可能遇到的困难 20314.3.4 引入中介者 20514.4 小结 207第 15章 装饰者模式 20915.1 给对象动态添加职责 21015.2 模拟传统面向对象语言的装饰者模式 21015.3 装饰者也装器 21115.4 回到Javascript的装饰者 21215.5 装饰函数 21315.6 用AOP装饰函数 21515.7 AOP的应用实例 21715.7.1 数据统计上报 21715.7.2 统计函数执行时间 21815.7.3 用AOP动态改变函数的参数 21915.7.4 插件式的表单验证 22115.8 装饰者模式和代理模式 22415.9 小结 224第 16章 状态模式 22516.1 初识状态模式 22516.1.1 第 一个例子:电灯程序 22616.1.2 状态模式电灯程序 22716.2 状态模式的定义 23116.3 状态模式的通用结构 23116.4 缺少抽象类的变通方式 23216.5 另一个状态模式示例——文件上传 233
摘要与插图
第pan style="font-family:宋体">章面向对象的JavascriptJavascript没有提供传统面向对象语言中的类式继承,而是通过原型委托的方式来实现对象与对象之间的继承。Javascript 也没有在语言层面提供对抽象类和接口的支持。正因为存在这些跟传统面向对象语言不一致的地方,我们在用设计模式编写代码的时候,更要跟传统面向对象语言加以区别。所以在正式学模式之前,我们有必要先了解一些Javascript在面向对象方面的知识。1.pan>动态类型语言和鸭子类型编程语言按照数据类型大体可以分为两类,一类是静态类型语言,另一类是动态类型语言静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行的时候,待变量被赋予某个值之后,才会具有某种类型。静态类型语言的优点首先是在编译时能发现类型不匹配的错误,编辑器可以帮助我们提前避免程序在运行期间有可能发生的一些错误。其次,如果在程序中明确地规定了数据类型,编译器还可以针对这些信息对程行一些优化工作,提高程序执行速度。静态类型语言的缺点首先是迫使程序员依照强契约来编写程序,为每个变量规定数据类型,归根结底只是辅助我们编写可靠高程序的一种手段,而不是编写程序的目的,毕竟大部分人编写程序的目的是为了完成需求交付生产。其次,类型的声明也会增加更多的代码,在程序编写过程中,这些细节会让程序员的精力从思考业务逻辑上分散开来。动态类型语言的优点是编写的代码数量更少,看起来也更加简洁,程序员可以把精力更多地放在业务逻辑上面。虽然不区分类型在某些情况下会让程序变得难以理解,但整体而言,代码量越少,越专注于逻辑表达,对阅读程序是越有帮助的。动态类型语言的缺点是无法保证变量的类型,从而在程序的运行期有可能发生跟类型相关的错误。这好像在商店买了牛肉辣条,但是要真正吃到嘴里才知道是不是牛肉味。在Javascript中,当我们对一个变量赋值时,显然不需要考虑它的类型,因此,Javascript是一门典型的动态类型语言。动态类型语言对变量类型的宽容给实际编码带来了很大的灵活。由于无行类型检测,我们可以尝任何对象的任意方法,而无需去考虑它原本是否被设计为拥有该方法。这一切都建立在鸭子类型(duck typing)的概念上,鸭子类型的通俗说法是:“如果它走起路来像鸭子,叫起来也是鸭子,那么它是鸭子。”我们可以通过一个小故事来更深刻地了解鸭子类型。从前在Javascript国里,有一,他觉得世界上美妙的声音是鸭子的叫声,于召集大臣,要组建一个1000只鸭子组成的合唱团。大臣们找遍了全国,终于找到999只鸭子,但是始终还差一只,后大臣发现有一只的鸡,它的叫声跟鸭子一模一样,于是这只鸡成为了合唱团的后一员。这个故事告诉我们要听的只是鸭子的叫声,这个声音的主人到底是鸡还是鸭并不重要。鸭子类型指导我们只关注对象的行为,而不关注对象本身,也是关注HAS-A,而不是IS-A。
……


