看完了《JavaScript王者归来》,在图书馆找了《JavaScript设计模式》来看,之前设计模式方面的书看过:《Head First 设计模式》、《设计模式之禅》,GOF的《Design Patterns: Elements of Reusable Object-Oriented Software》看了一部分。记得以前没这些基础的时候,看《JavaScript设计模式》简直是不知道作者在说什么。
言归正传:
准确的说,JavaScript没有类的概念,都是对象,JavaScript是基于面向对象的语言,但是《JavaScript设计模式》的作者们非要说JavaScript是面向对象的(也不知道是不是翻译的过程中问题)。用JavaScript来描述那些设计模式的时候,需要通过JavaScript的一些特性(比如说闭包、原型)来模拟Java、C++等面向对象语言的一些特性(比如说类、接口、继承、public、private)。
书中说了三种模拟Interface的方法
第一种:用注释描述接口
我觉得这个就是一种内部约定,直接说“我实现了XX接口”,在语言上我个人觉得一点约束力都没有,这真不应该拿出来说,有点滥竽充数的感觉。
第二种:用属性检查模仿接口
需要一个叫做implements()的函数进行检查
function implements(object){
for(var i=1;i<arguments.length;i++){
var interfaceName = arguments[i];
var interfaceFound = false;
for(var j=0;j<object.implementsInterfaces.length;i++){
if(object.implementsInterfaces[j] == interfaceName){ //implementsInterfaces保存了接口定义的方法的名称
interfaceFound = true;
break;
}
}
if(!interfaceFound){
return false; //接口没有找到
}
}
return true;
}
这是《JavaScript设计模式》书中的一部分代码,作者的描述是这样的:
这种方法有几个优点。它对类所实现的接口提供了文档说明。如果需要的接口不在一个类宣称支持的接口之列,你会看到错误消息。通过利用这些错误,你可以强迫其他程序员声明这些接口。这种方法的主要缺点在于它并未确保类真正实现了自称实现的接口。只知道它是否说自己实现了接口,在创建一个类声明它实现了一个接口,但后来在实现该接口方法所规定的方法时却漏掉其中的某一个,找一个错误很常见,此时所有的检查都能通过,但那个方法却并不存在,这将在代码中埋下一个隐患。
随即引出了第三中方法:用鸭式辨型模仿接口
原理:如果对象具有与接口定义的方法同名的所有方法,那么就可以认为它实现了这个接口。
首先需要一个接口类Interface
var Interface = function(name ,methods){
……
}
接受两个参数:接口名称,方法名
这个Interface类还有一个静态方法 ensureImplements()
Interface.ensureImplements = function(object){
……
}
实际用法是这样的:
var Composite = new Interface('Composite',['add','remover','getChild']);
var FormItem = new Interface('FormItem',['save']);
var CompositeForm = function(id,method,action){
……
}
function addForm(formInstance){
ensureensureImplements(formIntance,Composite,FormItem);
//This function will throw an error if a required method is not implemented
……
}
最后作者采用第一种和第三种方法实现接口,代码如下:
var Interface = function(name,methods){
if(arguments.length!=2){
throw new Error("Interface constructor called with"+arguments.length+
"arguments,but expected exactly 2.");
}
this.name = name;
this.methods=[];
for(var i=0, len = methods.length;i<len;i++){
if(type methods[i] !=='string'){
throw new Error("Interface constructor expects method names to be passed in as a string");
}
this.methods.push(methods[i]);
}
};
Interface.ensureImplements = function(object){
if(arguments.length<2){
throw new Error("Function Interface.ensureImplements call with"+arguments.length
+"arguments,but expected at least 2.");
}
for(var i=1,len = arguments.length;i<len;i++){
var interface = arguments[i];
if(interface.constructor !== Interface){
throw new Error("Function Interface.ensureImplements expects arguments two and "+
"above to be instance 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 implements the"+interface.name+"interface.Method"+method+"was not found");
}
}
};
设计模式在我的理解就是四个字:解耦、复用。
可能是我现在需求还没那么高,,没办法理解设计模式在JavaScript里作用