The first important content in this book is interfaces.
Everyone should be familiar with interfaces. Simply put, an interface is a contract or specification. In a strongly typed object-oriented language, interfaces can be easily implemented. However, there is no native way to create or implement interfaces in JavaScript, or to determine whether a type implements a certain interface. We can only use the flexibility of js to simulate interfaces.
There are three ways to implement interfaces in JavaScript: annotation description, attribute verification, and duck model.
note: Because I am reading an English book and my translation skills are limited, I don’t know how to translate some words. You can only understand the spirit.
1. Describing Interfaces with Comments
Example:
/*
interface Composite {
Function add(child);
function remove(child);
function getChild(index);
}
interface FormItem {
function save();
}
*/
var CompositeForm = function(id, method, action) { // implements Composite, FormItem
...
};
//Implement the Composite interface.
CompositeForm.prototype.add = function(child) {
...
};
CompositeForm.prototype.remove = function(child) {
...
};
CompositeForm.prototype.getChild = function(index) {
...
};
// Implement the FormItem interface.
CompositeForm. prototype.save = function() {
...
};
Simulate other object-oriented languages, use the interface and implements keywords, but you need to annotate them, so There will be no grammatical errors.
The purpose of this is just to tell other programmers what methods these classes need to implement and need to pay attention to when programming. However, it does not provide a verification method to see whether these classes correctly implement the methods in these interfaces. This method is a documented approach.
2. Emulating Interfaces with Attribute Checking
Example:
/* interface
Composite {
function add(child);
function remove(child);
function getChild(index);
}
interface FormItem {
function save();
}
*/
var CompositeForm = function(id, method, action) {
this.implementsInterfaces = ['Composite', 'FormItem'] ;
...
};
...
function addForm(formInstance) {
if(!implements(formInstance, 'Composite', 'FormItem')) {
throw new Error("Object does not implement a required interface.");
}
...
}
// The implements function, which checks to see if an object declares that it
// implements the required interfaces.
function implements(object) {
for(var i = 1; i < arguments.length; i ) {
// Looping through all arguments
// after the first one.
var interfaceName = arguments[i];
var interfaceFound = false;
for(var j = 0; j < object.implementsInterfaces.length; j ) {
if(object.implementsInterfaces[j] == interfaceName) {
interfaceFound = true;
break;
}
if(!interfaceFound) {
return false;
// An interface was not found.
}
}
return true; An improvement over the first method, the definition of the interface is still implemented in the form of annotations, but a verification method is added to determine whether a type implements a certain interface.
3. Emulating Interfaces with Duck Typing
Copy code
The code is as follows:
// Interfaces.
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);
var FormItem = new Interface('FormItem', ['save']);
// CompositeForm class
var CompositeForm = function(id, method, action) {
...
};
...
function addForm(formInstance) {
ensureImplements(formInstance, Composite, FormItem);
// This function will throw an error if a required method is not implemented.
...
}
// Constructor.
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(typeof methods[i] !== 'string') {
throw new Error("Interface constructor expects method names to be "
"passed in as a string.");
}
this.methods.push(methods[i]);
}
};
// Static class method.
Interface.ensureImplements = function(object) {
if(arguments.length < 2) {
throw new Error("Function Interface.ensureImplements called 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 instances 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 implement the " interface.name " interface. Method " method " was not found.");
}
}
}
};
何时使用接口?
一直使用严格的类型验证并不适合,因为大多数javascript程序员已经在没有接口和接口验证的情况下编程多年。当你用设计模式开始设计一个很复杂的系统的时候,使用接口更有益处。看起来使用接口好像限制了javascript的灵活性,但实际上他让你的代码变得更加的松耦合。他使你的代码变得更加灵活,你可以传送任何类型的变量,并且保证他有你想要的方法。有很多场景接口非常适合使用。
在一个大型系统里,很多程序员一起参与开发项目,接口就变得非常必要了。程序员经常要访问一个还没有实现的api,或者为其他程序员提供别人依赖的一个方法存根,在这种情况下,接口变得相当的有价值。他们可以文档化api,并作为编程的契约。当存根被实现的api替换的时候你能立即知道,如果在开发过程中api有所变动,他能被另一个实现该接口的方法无缝替换。
如何使用接口?
首先要解决的问题是,在你的代码中是否适合使用接口。如果是小项目,使用接口会增加代码的复杂度。所以你要确定使用接口的情况下,是否是益处大于弊端。如果要使用接口,下面有几条建议:
1.引用Interface 类到你的页面文件。interface的源文件你可以再如下站点找到: http://jsdesignpatterns.com/.
2.检查你的代码,确定哪些方法需要抽象到接口里面。
3.创建接口对象,没个接口对象里面包含一组相关的方法。
4.移除所有构造器验证,我们将使用第三种接口实现方式,也就是鸭子类型。
5.用Interface.ensureImplements替代构造器验证。
Statement:The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn