我见过以不同方式实现的模式,但想法很简单:
- 你有一些类——你的接口——它只是指定了一些函数的名称。(您可能希望有一个名为 Interface 的类,您的实际接口实例化该类,这样您的接口就属于 Interface 类型)
- 然后你有一些其他类实现了这样的接口。这意味着第二个类必须至少具有接口指定的所有功能。
- 最后,您在其他地方还有一些其他功能,它期望接收一个实现接口的对象。在您提到的示例代码中,此函数是 addForm,它需要一个实现“Composite”和“FormItem”接口的对象。
- 然后,此函数循环遍历它期望的接口的所有方法,并检查您传递给它的对象是否也具有这些方法。如果在传递给函数的对象中找不到来自某个接口的方法,则确定该对象未实现该接口,并引发异常。
由于涉及的开销,有些人可能会发现这种模式不切实际,但鉴于 Javascript 缺乏对接口的本地支持,这不是一个太糟糕的解决方案。有些人可能还会发现在 Javascript 中为小型项目使用接口是多余的。
例子
var Interface = function(name, methods) {
this.name = name;
this.methods = [];
if (methods.constructor == Array)
this.methods = methods;
else if (methods.constructor == String)
this.methods[0] = methods;
else
throw new Error("Interface must define methods as a String or an Array of Strings");
};
var InterfaceHelper = {
ensureImplements : function(obj, interfaces) {
// If interfaces is not an array, assume it's a function pointer
var toImplement = interfaces.constructor == Array ? interfaces : [interfaces];
var interface;
// For every interface that obj must implement:
for (var i = 0, len = toImplement.length; i < len; i++) {
interface = toImplement[i];
// Make sure it indeed is an interface
if (interface.constructor != Interface)
throw new Error("Object trying to implement a non-interface. "
+ interface.name + " is not an Interface.");
// Make sure obj has all of the methods described in the interface
for (var j = 0, interfaceLen = interface.methods.length; j < interfaceLen; j++)
if (!obj[interface.methods[j]])
throw new Error("Interface method not implemented. "
+ interface.name + " defines method " + interface.methods[j]);
}
return true;
}
};
var Drawable = new Interface("Drawable", ["onDraw"]);
var Surface = function() {
this.implements = ["Drawable"];
this.onDraw = function() {
console.log("Surface Drawing");
};
};
用法
var myDrawableSurface = new Surface();
// Returns true
InterfaceHelper.ensureImplements(myDrawableSurface, Drawable);
// Returns false (Error thrown)
InterfaceHelper.ensureImplements(myDrawableSurface, Array);