这几天看《Javascript设计模式》。第一个感受是翻译真不怎样。其次受益良多。这里先记下初步的理解,以后慢慢补充、深入。
设计模式本质上是针对某一类特定问题的解决方案,并且这些解决方案经过社区的广泛试验被认为是行之有效的。作者将javascript设计模式划分为三大类:创建型、结构型、行为型。当然书中只是介绍了最常见的那些。
创建型有:Constructor、Factory、Prototype、Abstract、singleton、Builder,其中前三个在《JavaScript高级程序设计》中已经有介绍。
结构型有:Decorator、Facade、Flyweight、Adapter、Proxy,主要体现在不同对象间的联系方法。
行为型有:Iterator、Mediator、Observer、Visitor,改善、简化不同对象间通信。
1.Constructor模式:JS传统的创建对象方式。new Fn创建对象,其流程是先创建一个空对象实例,再执行Fn中的代码,一般是用this给对象赋与属性/方法,然后返回该新对象。这种方法的缺点比较明显,首先是创建多个实例时,每个新实例都各自创建相同的方法,这些方法功能相同,完全没必要在每个实例中重复创建;同样,如果有相同的内部属性,也不需要在Fn中重复赋予,相同的静态的属性/方法可以在写在prototype中,所以后来发展出了现在主流的constructor+prototype模式。动态的属性作为Fn参数传入赋值给this,动态方法在创建实例后赋予,以减少不必要的重复。
2.Prototype模式:原型模式在书中的介绍跟我认为的有些出入,或者书中的原型模式比较纯粹,用ECMAScript5的Object.create(prototype,options)方法给一个对象赋予原型;在避免Object.create方法时,通过'创建prototype'-'创建空构造函数'-'将prototype赋予空构造函数的prototype'-'new 构造函数'的流程创建基于prototype的实例,是的,只是单纯的原型继承。
3.Factory模式:工厂模式的特点是,调用工厂函数时,内部创建一个实例,并将其返回。以前看高级程序设计时,了解不多,只觉得是一种不必要的冗余的模式,但现在发现存在即道理,假设应用程序中有可能动态的生成某一类对象的具体实例,这些对象实例中有多种变体,这意味着可能需要多个构造函数,使用工厂模式可以帮我们封装创建实例的具体实现,只需要把类型和相关属性作为参数传入工厂函数即可。所以书中提醒我们什么时候适合使用:
*当对象或组件设计高复杂性时
*需根据不同环境动态生成不同实例时
*处理很多共享相同属性的对象/组件时
*在编写只需要一个API契约(鸭子类型)的其他对象的实例对象时,有助于解耦。(有疑惑)
什么时候不适合:
*应用程序错误时,会带来大量不必要的复杂性,推荐使用显式的的构造函数
*可能给单元测试带来问题(创建过程隐藏在接口之后)
另外还有抽象工厂,旨在将创建实例的过程剥离,让系统独立于这些代码。这部分先保留,以后再研究。
4.Singleton:单例模式,往往在应用程序中用以实现某特定功能,如字面意思,在全局中改类只实例化一次,但再次实例化时只是返回它本身。它的功能可以很丰富,视需要而定。比如用来生成唯一序列码、保存“调度多个对象的方法”。
5.Decorator模式:装饰模式比较有意思,书中的举例是,游戏角色可能佩戴不同的装备,角色本身有其独立的功能代码,装备能赋予角色额外的功能,所以装饰模式就是一系列独立于对象实例的代码,这些代码可以扩展实例对象的功能,但并不直接改变实例本身。比如一个功能函数Fn1(archer)=>attack_power;
6.Facade模式:外观模式这个名字好怪。其本意是,一段代码里面可能有复杂的实现,用以完成某一目标功能,比如兼容各个浏览器的事件绑定,对外只提供一个简洁的接口,只需要传入事件类型及回调,开发者不需要了解其内部实现,典型的例子是jQ的各中接口方法。
7.Flyweight模式:享元模式,本意是说,将各个对象中相似的对象或数据结构剥离出来存放在外部的一个结构中,存放并管理,让系统更简洁结构更清晰(我是这么认为...)。其应用主要有数据层和DOM层两方面:
*数据层,主要是将系统中各个对象可以共享的数据/状态变量独立出来并进行管理,这里不得不想起vuex。
*DOM层,书上举得例子是事件委托。。。。比如一个ul中的li,如果触发的事件是类似的,可以委托到顶层,这就避免注册多个事件、减少了内存。
8.Observer模式:耳熟能详的观察者模式,即是说,一个主体状态发生了改变时,与之关联的观察者收到"状态改变"的信息并执行相应的update(反应)。就具体实现而言,主体有个观察者列表,具有一系列的操作列表的方法以及发送消息的方法,发送消息就是:在观察者列表中引用每个观察者的update方法。所以说,这种模式下,主体占据主动权。在JavaScript中是以Publish/Subscript(发布/订阅)的模式实现的,简单点说就是事件机制。不过在各大js框架中都有pub/sub机制的实现,当然,需不需要就看个人了。
9.Mediator模式:中介者模式,主要意思是,系统中各组件/对象的通信,经由mediator转发,使得各部分之间相对独立。
今天先写这么多
1.Constructor模式:JS传统的创建对象方式。new Fn创建对象,其流程是先创建一个空对象实例,再执行Fn中的代码,一般是用this给对象赋与属性/方法,然后返回该新对象。这种方法的缺点比较明显,首先是创建多个实例时,每个新实例都各自创建相同的方法,这些方法功能相同,完全没必要在每个实例中重复创建;同样,如果有相同的内部属性,也不需要在Fn中重复赋予,相同的静态的属性/方法可以在写在prototype中,所以后来发展出了现在主流的constructor+prototype模式。动态的属性作为Fn参数传入赋值给this,动态方法在创建实例后赋予,以减少不必要的重复。
2.Prototype模式:原型模式在书中的介绍跟我认为的有些出入,或者书中的原型模式比较纯粹,用ECMAScript5的Object.create(prototype,options)方法给一个对象赋予原型;在避免Object.create方法时,通过'创建prototype'-'创建空构造函数'-'将prototype赋予空构造函数的prototype'-'new 构造函数'的流程创建基于prototype的实例,是的,只是单纯的原型继承。
3.Factory模式:工厂模式的特点是,调用工厂函数时,内部创建一个实例,并将其返回。以前看高级程序设计时,了解不多,只觉得是一种不必要的冗余的模式,但现在发现存在即道理,假设应用程序中有可能动态的生成某一类对象的具体实例,这些对象实例中有多种变体,这意味着可能需要多个构造函数,使用工厂模式可以帮我们封装创建实例的具体实现,只需要把类型和相关属性作为参数传入工厂函数即可。所以书中提醒我们什么时候适合使用:
*当对象或组件设计高复杂性时
*需根据不同环境动态生成不同实例时
*处理很多共享相同属性的对象/组件时
*在编写只需要一个API契约(鸭子类型)的其他对象的实例对象时,有助于解耦。(有疑惑)
什么时候不适合:
*应用程序错误时,会带来大量不必要的复杂性,推荐使用显式的的构造函数
*可能给单元测试带来问题(创建过程隐藏在接口之后)
4.Singleton:单例模式,往往在应用程序中用以实现某特定功能,如字面意思,在全局中改类只实例化一次,但再次实例化时只是返回它本身。它的功能可以很丰富,视需要而定。比如用来生成唯一序列码、保存“调度多个对象的方法”。
5.Decorator模式:装饰模式比较有意思,书中的举例是,游戏角色可能佩戴不同的装备,角色本身有其独立的功能代码,装备能赋予角色额外的功能,所以装饰模式就是一系列独立于对象实例的代码,这些代码可以扩展实例对象的功能,但并不直接改变实例本身。比如一个功能函数Fn1(archer)=>attack_power;
6.Facade模式:外观模式这个名字好怪。其本意是,一段代码里面可能有复杂的实现,用以完成某一目标功能,比如兼容各个浏览器的事件绑定,对外只提供一个简洁的接口,只需要传入事件类型及回调,开发者不需要了解其内部实现,典型的例子是jQ的各中接口方法。
7.Flyweight模式:享元模式,本意是说,将各个对象中相似的对象或数据结构剥离出来存放在外部的一个结构中,存放并管理,让系统更简洁结构更清晰(我是这么认为...)。其应用主要有数据层和DOM层两方面:
*数据层,主要是将系统中各个对象可以共享的数据/状态变量独立出来并进行管理,这里不得不想起vuex。
*DOM层,书上举得例子是事件委托。。。。比如一个ul中的li,如果触发的事件是类似的,可以委托到顶层,这就避免注册多个事件、减少了内存。
8.Observer模式:耳熟能详的观察者模式,即是说,一个主体状态发生了改变时,与之关联的观察者收到"状态改变"的信息并执行相应的update(反应)。就具体实现而言,主体有个观察者列表,具有一系列的操作列表的方法以及发送消息的方法,发送消息就是:在观察者列表中引用每个观察者的update方法。所以说,这种模式下,主体占据主动权。在JavaScript中是以Publish/Subscript(发布/订阅)的模式实现的,简单点说就是事件机制。不过在各大js框架中都有pub/sub机制的实现,当然,需不需要就看个人了。
9.Mediator模式:中介者模式,主要意思是,系统中各组件/对象的通信,经由mediator转发,使得各部分之间相对独立。
今天先写这么多