模式 Patterns
简介
一群无法无天的猪从无辜的小鸟那里偷走了所有的前端架构,现在小鸟们要把它们夺回来!一队特殊的小鸟英雄将攻击这些卑鄙的猪,直到夺回原本属于它们的前端 JavaScript 架构!
小鸟们最终会成功吗?它们会打败那些培根味儿的敌人吗?让我们一起揭示 JavaScript 之愤怒的小鸟系列的另一个扣人心弦的章节!
译注:翻译“bacon flavored foe”时,想起来了《少林足球》里的“做人如果没有梦想,那跟咸鱼有什么区别?”,就翻译成了“咸猪敌人”,@sunnylost 建议翻译为“培根味儿的敌人”,应该更准确和有趣些。
阅读系列介绍文章,查看所有小鸟以及它们的攻击力。
战报
- Red Bird - IIFE
- Blue Bird - Events
- Yellow Bird - RequireJS
- Black Bird - Backbone
- White Bird - Linting
- Green Bird - Mocking
- Orange Bird - Templating
大鸟哥的攻击
在这篇文章中,我们将看到大鸟哥祭出它的大规模杀伤性武器:有限状态机以及成熟的设计模式。渐渐的,小鸟们将一个接一个的夺回属于它们的东西!
猪偷走了什么?
小鸟们了解如何编程的大部分知识,但是从未形成通用的术语,一些代表了常见场景、同时能被大家理解的术语。然后某一天大鸟哥出现了,并记录了一组常见的设计模式的名称和描述,这样它们在谈论架构时就可以达成共识(就有了共同的语言)。最终大鸟哥的模式广受欢迎,并以四人帮一书闻名于鸟界。
译注:这段文字欢乐的很。
然而在最近的一次猪群入侵中,小鸟们的四人帮书惨重失窃!现在,大鸟哥被派去找回被盗的书。它将用压到一切诡计的力量摧毁猪群,夺回属于它们的东西。
鸟界的四人帮(23 种)
创建模式(5 种)
创建模式涉及到将对象实例化,这类模式都提供一个方法,将客户从所需实例化的对象中解耦。
- Abstract Factory
抽象工厂。提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。 - Builder
构造器。封装一个产品的构造过程,并允许按步骤构造。 - Factory Method
工厂方法。定义了一个创建对象的方法,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。 - Prototype
原型。当创建给定类的实例的过程很昂贵或很复杂时,就使用原型模式。 - Singleton
单例。确保一个类只有一个实例,并提供一个全局访问点。
结构模式(7 种)
结构模式可以让你把类或对象组合到更大的结构中
- Adapter
适配器。将一个类的接口,转换成客户期望的另一个接口。适配器让原来接口不兼容的类可以合作无间。 - Bridge
桥接。不只改变你的实现,也改变你的抽象。 - Composite
组合。允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。 - Decorator
装饰者。动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 - Facade
外观。提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。 - Flyweight
蝇量。让某个类的一个实例能用来提供许多“虚拟实例”。 - Proxy
代理。为另一个对象提供一个替身或占位符以控制对这个对象的访问。
行为模式(11 种)
- Chain of Resp.
责任链。让一个以上的对象有机会处理某个请求。 - Command
命令。将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。 - Interpreter
解释器。为语言创建解释器。 - Iterator
迭代器。提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。 - Mediator
中介者。集中相关对象之间复杂的沟通和控制方式。 - Memento
备忘录。让对象返回之前的状态。 - Observer
观察者。定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 - State
状态。允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。 - Strategy
策略。定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。 - Template Method
模板方法。在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。 - Visitor
访问者。当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式。
JavaScript 中的设计模式
单例模式
单例模式最简单的实现是采用对象字面量,如下面的代码所示。基本上,我们只是创建了一个对象,含有一些属性。从技术角度讲,有人可能会建议使用 Object.create
,但是大部分情况下,对象字面量符合单例模式的定义。你可以在本文末尾的推荐资源中找到更强大的解决方案。
译注:Object.create(proto [, propertiesObject ]) 创建一个拥有指定原型和若干个指定属性的对象。
工厂模式
工厂模式实际是一种不使用 new
关键字来创建新对象的方式。理念是在工厂方法中提取抽象。在下面的例子中,我们不一定要做很多事情,但是你可以想象的到,我们可以沿着这个方向添加一些自定义代码和不会改变的额外 API,这才是工厂模式的关键点所在。
桥接模式
在下面的代码片段中,我们在事件处理函数和将要执行的代码(getUrl( url, callback )
)之间建立了一个简单的桥接。从而使得被执行的代码(getUrl( url, callback )
)更易于测试,因为它不再依赖于 jQuery 传入的上下文元素。
外观模式
外观模式在 Web 前端开发中很普遍,因为有如此多的跨浏览器不一致问题。外观模式为这种不一致提供了一个统一的 API。在下面的代码中,我们将 addEventListener 在不同浏览器中的实现进行逻辑抽象。
适配器模式
一个适配器可以轻量的处理一段代码,让其与另一段代码无间合作。当你需要切换到另一个库又无法忍受重写大量代码时,适配器会非常有用。在下面的示例中,我们将修改 jQuery 的 $.when
方法以支持 WinJS.Promise
。这是我在 appendTo 工作期间写下的代码,当时我们想让 Windows 8 APP 可以使用 jQuery。你可以在 jquery-win8 找到这个库。
jquery-win8 库的大部分功能已经不再需要了,因为 Jonathan Sampson 已经与 jQuery 开发团队一起协作,以确保他对这一垫片的更新被添加到 jQuery 2.0 版本中,这篇文章记录了这一点。
观察者模式
我们已经在这个系列的 Blue Bird 一文中阐述了观察者模式,这是一个功能强大的模式,可以实现各种组件的解耦。个人推荐使用 postal.js 库。
更多模式
继承
在 JavaScript 中有多种方式实现继承。当你在应用程序中创建对象时,最好了解一下这些模式。
原型继承
模拟继承
链式语法
因为 jQuery 库的缘故,链式语法在前端界变得非常流行。实际上这是一种非常容易实现的模式。基本上,你只需要让每个函数返回 'this',这样其他函数就可以立即被调用。看看下面的例子。
封装模式
我们在 Red Bird 一文中已经阐述了封装模式,不过当时说的 IIFE 模式。封装模式允许你拥有公共和私有的属性和方法,以此来封装你的代码。下面是一个非常简单的示例。更多细节请参阅文章 Red Bird。
有限状态机
有限状态机是我最喜欢的模式之一。我的朋友 Jim Cowart(@ifandelse)创建了 Machina.js 库,用来在 JavaScript 中实现这一模式。下面的示例使用状态来描述愤怒的小鸟游戏。更多信息请参阅它的博客文章和 GitHub 库。
建议
除了学习这些模式之外,我建议你挑一个喜欢的库,并钻研它们的源代码。在其中你可以学到丰富的知识。起初你可能觉得云山雾罩,但过一段时间你可以从真正理解这些模式的开发者身上收集到大量的模式。你也可以试着只着眼于一个特别的方法并剖析它。如果你不知道到底要去哪里寻找这么一个特别的方法,那么为什么不选择 jQuery 并使用 James Padolsey(@padosley)的 jQuery 源码查看器来帮助你寻找呢?
其他资源
已经有太多的模式以至我无法在这里一一列出。在我之前,已经有许多人撰写了关于这些模式的博客,并且以后还会有。如果我错过了什么好模式,请告诉我。
- JavaScript Design Patterns by Joe Zim (@JoeZimJS)
- JavaScript Design Patterns by Joe Zim (@JoeZimJS)
- Understanding Design Patterns in JavaScript by Tilo Mitra (@tilomitra)
- Learning JavaScript Design Patterns by Addy Osmani (@addyosmani)
- JS Patterns by Shi Chuan (@shichuan)
- JavaScript Patterns by Stoyan Stefanov (@xyz)
- JavaScript: The Good Parts by Douglas Crockford
攻击!
下面是一个用 boxbox 构建的简版 Angry Birds,boxbox 是一个用于 box2dweb 的框架,由 Bocoup 的 Greg Smith 编写。
按下
空格键
来发射大鸟哥,你也可以使用方向键。
结论
好消息是,你不必知道所有的答案也顺利完成 Web 前端开发,但多少了解一些开发中反复遇到的通用模式确实很有帮助。一旦你习惯了这些模式,谈论架构方案将变得更容易,也可以更快的找出解决方案。花一些时间浏览前面推荐的资源,然后仔细考虑那些适合你的模式。
还有更多的前端架构技术被猪偷走了。在下篇文章中,另一只愤怒的小鸟将继续复仇!Dun, dun, daaaaaaa!
@sunnylost 补充:Dun, dun, daaaaaaaaaa! 应该是在模拟背景音乐,类似于这种 http://missingno.ocremix.org/musicpages/game_on.html
blog comments powered by Disqus