为了解决实例化对象产生大量重复的问题。
工厂模式分为简单工厂、抽象工厂和智能工厂,工厂模式不显示地要求使用一个构造函数。
- 简单工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口,即创建什么样的实例由传入的参数决定。实际上在js里面,所谓的构造函数也是一个简单工厂。只是批了一件new的衣服,本身只是一个对象的复制和改写过程, 而具体会生成什么是由调用ObjectFactory时传进去的参数所决定的;
- 复杂工厂模式:使用子类来决定一个成员变量应该是哪个具体的类的实例。一般性的代码集中在父类中,个性化的代码在子类中单独定制。父类定义通用的方法,而子类继承父类然后实现自己的方法,调用时直接调用子类的相关方法来实现,而父类的方法不能直接调用;
- 抽象工厂:它用于封装一组具有共同目标的单个工厂。它能够将一组对象的实现细节从一般用法中分离出来。应当使用抽象工厂模式的情况是:一个系统必须独立于它所创建的对象的生成方式,或它需要与多种对象类型一起工作。
何时使用工厂模式?
Factory模式主要在以下场景使用:
- 当对象或组件涉及高复杂性时
- 当需要根据所在的不同环境轻松生成对象的不同实例时
- 当处理很多共享相同属性的小型对象或组件时
Ensure a class has only one instance and provide a global point of access to it.
单例模式的定义是产生一个类的唯一实例
在类中要判断是否已经有了一个实例,如果没有才创建,否则返回已有的。
需要使用闭包,在类中定义来避免改变外部变量
//eg.1
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
//eg.2
var createMask = function(){
var mask;
return function(){
return mask || ( mask = document.body.appendChild( document.createElement('div') ) )
}
}();
使用原型构造实例,最简单的实现就是js中的Object.create(proto)
我们可以认为 Prototype 模式是基于原型继承的模式,可以在其中创建对象,作为其他对象的原型。prototype对象本身实际上是用作构造函数创建每个对象的蓝图。如果所用构造函数的原型包含一个名为 name 的属性(代码样例如下),那么由同样的构造函数创建的每个对象也会有同样的属性,其中一个好处是,在一个对象中定义一个函数,它们都是由引用创建,而不是创建它们自己的单份拷贝,因此可以带来性能提升。
一种在内存已分配给该对象的情况下,用于初始化新创建对象的特殊方法。
在js中通过在构造器函数前加上new关键字来实例化一个新对象,在构造器内部,关键字this引用信创建的对象。
还可以使用带原型的构造器,新对象会具有构造器原型的所有属性;
基于对象字面量,模块模式用于进一步模拟类的概念,通过这种方式,能够是一个单独的对象拥有公有,私有方法和变量,从而屏蔽来自全局作用域的特殊部分,函数名与页面上其他脚本定义的函数冲突的可能性降低;
Module模式使用闭包封装“私有”状态和组织,提供了一种包装混合公有私有方法和变量的方式,防止其泄漏至全局作用域,通过该模式,只需返回一个公有API,而其他的一切都维持在私有闭包里,由于闭包的存在,声明的变量和方法只在该模式内部可用,但在返回的对象上定义的变量和方法,则对外部使用者都是可用的。
在模块模式中,代码的共有部分能够接触私有部分,然而外界无法接触类的私有部分。
一个更新的模式,能够在私有范围内简单定义所有的函数和变量,并返回一个匿名对象,拥有指向私有函数的指针,该函数是他希望展示为公有的方法。
一个subject对象维持一系列依赖于它(观察者)的对象,将有关状态的任何变更自动通知给它们,当一个目标需要告诉观察者发生了什么有趣的事情,它会向观察者广播一个通知(可以包括与通知主题相关的特定数据)。
Publish/Subscribe 模式使用了一个主题/事件通道,这个通道介于希望接收到通知(订阅者)的对象和激活事件的对象(发布者)之间。该事件系统允许代码定义应用程序的特定事件,这些事件可以传递自定义参数,自定义参数包含订阅者所需的值。其目的是避免订阅者和发布者之间产生依赖关系。这与 Observer 模式不同,因为它允许任何订阅者执行适当的事件处理程序来注册和接收发布者发出的通知。
这里的中心思想是促进松散耦合。通过订阅另一个对象的特定任务或活动,当任务/活动发生时获得通知,而不是单个对象直接调用其他对象的方法。
中介者是一种行为设计模式,它允许我们公开一个统一的接口,系统的不同部分可以通过该接口进行通信。
本质上是Observer模式的共享目标。它假设该系统中对象或模块之间的订阅和发布关系被牺牲掉了,从而维护中心联络点。它也可能被认为是额外的或者是用于应用程序间的通知,如不同子系统之间的通信,这些子系统本身就很复杂,且可能希望通过发布/订阅关系实现内部组件间的解耦。
在Observer模式中,不存在封装约束的单一对象。Observer和Subject (目标)必须合作才能维持约束。Communication(通信)模式由观察者和目标互连的方式所决定:单一目标通常有很多观察者,有时一个目标的观察者是另一个观察者的目标。 Mediator和Observer都能够促进松耦合;然而,Mediator模式通过限制对象严格通过Mediator进行通信来实现这一目的。Observer模式创建观察者对象,观察者对象向订阅它们的对象发布其感兴趣的事件。
Command 模式旨在将方法调用、请求或操作封装到单一对象中,从而根据我们不同的请求对客户进行参数化和传递可供执行的方法调用。
Command 模式背后的主要思想是:它为我们提供了一种分离职责的手段,这些职责包括从执行命令的任意地方发布命令以及将该职责转而委托给不同对象。实施明智的、简单的命令对象将把action动作和调用该动作的对象绑定在一起。它们始终包括一个执行操作(如 run()或 execute())。所有具有相同接口的 Command对象可以根据需要轻松交换,这被认为是该模式的一个更大好处。
即命令,操作的对象等作为参数传递,在方法内部根据不同参数执行不同的操作.
Facade 模式为更大的代码体提供了一个方便的高层次接口,能够隐藏其底层的真实复杂性。可以把它想成是简化API来展示给其他开发人员,通常都是可以提高可用性
Mixin是可以轻松被一个子类或者一组子类继承功能的类,目的是函数复用;
在JavaScript中,我们可以将继承Mixin看作为一种通过扩展收集功能的方式。我们定义的每个新对象都有一个原型,可以从中继承更多属性。原型可以继承于其他对象的原型,但更重要的是,它可以为任意数量的对象实例定义属性。可以利用这一点来促进函数复用
参考python的装饰器理解;
通常,Decorator提供了将行为动态添加至系统的现有类的能力。其想法是,装饰本身对于类原有的基本功能来说并不是必要的;否则,它就可以被合并到超类本身了。装饰者可以用于修改现有的系统,希望在系统中为对象添加额外的功能,而不需要大量修改使用它们的底层代码。开发人员使用它们的一个共同原因是,应用程序可能包含需要大量不同类型对象的功能。
装饰者模式不严重依赖于创建对象的方式,而是关注扩展其额外功能,使用了一个单一的基本对象并逐步添加提供额外功能的decorator,而不仅仅依赖于原型继承,这个想法是,向基本对象添加装饰属性或方法,而不是进行子类化,因此它较为精简;
旨在通过与相关的对象共享尽可能多的数据来减少应用程序中内存的使用;
Flyweight 数据共享会涉及获取多个对象使用的若干相似对象或数据结构,以及将这些数据放到一个单一的外部对象中。我们可以将该对象传递给依赖这些数据的对象,而不是在每一个对象都存储相同的数据。
Flyweight 模式的应用方式有两种。第一种是用于数据层,处理内存中保存的大量相似对象的共享数据。第二种是用于 DOM 层,Flyweight 可以用作中央事件管理器,来避免将事件处理程序附加到父容器中的每个子元素上,而是将事件处理程序附加到这个父容器上。
Composite模式描述了一组对象,可以使用与处理对象的单个实例同样的方式来进行处理。这使我们能够以统一的方式来处理单个对象和组合,这意味着不管我们正在处理的是一个项目还是一千个项目,都可以应用同样的行为。
Adapter模式将对象或类的接口(interface)转变为与特定的系统兼容的接口。适配器基本上允许类或函数在一起运行,通常并不是因为它们的不兼容接口。适配器将接口的调用转变为原始接口的调用,实现这个目的所需的代码通常是很少的。
Iterator 是一种设计模式,其中,迭代器(允许我们遍历集合的所有元素的对象)顺序访问聚合对象的元素,无需公开其基本形式。迭代器封装特定迭代如何发生的内部结构。对于jQuery的jQuery.fn.each()迭代器,我们实际上能够使用jQuery.each()后面的底层代码来遍历一个集合,而不需要阅读或理解提供这种功能的后台工作代码。这种模式可以被视为一种特殊的facade,我们显式地处理与迭代相关的问题。
使用DOM时,我们通常想动态创建新元素——一种增加复杂性的过程,取决于我们希望所创建元素包含的最终标记、属性和特性。
复杂的元素在定义时需要特别注意,特别是如果我们想灵活地从字面上定义元素的最终标记(可能会很混乱)或转而选择更易读的面向对象路由。拥有用于创建复杂的DOM对象并独立于对象本身的机制能够提供这种灵活性,而这正是Builder模式所提供的。
Builder 使我们能够仅通过指定对象的类型和内容就可以创建复杂的对象,而无需显式创建或表示该对象。使用 jQuery 美元符号可以实现这项功能,因为它提供了很多不同的方式来动态创建新jQuery(和DOM)对象,或者是通过为元素、部分标记和内容传递完整的标记,或者是使用jQuery来创建