/* interface Composite { function add(child); function remove(child); function getChild(index); } interface FormItem { function save(); } */ var CompositeForm = function(id, method, action) { // 定義接口類 ... }; // 爲接口類添加方法 CompositeForm.prototype.add = function(child) { ... }; CompositeForm.prototype.remove = function(child) { ... }; CompositeForm.prototype.getChild = function(index) { ... }; CompositeForm.prototype.save = function() { ... };
此種方法不易規範遵照,屬於程序文檔範疇,對接口的約定遵照全靠自覺。可是易於實現,不需額外的類或函數。javascript
/* 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."); } ... } // 檢查一個對象是否實現了須要的接口 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; j++) { if (object.implementsInterfaces[j] == interfaceName) { interfaceFound = true; break; } } if (!interfaceFound) { return false; // 未找到接口 } } return true; // 全部接口都找到了 }
此方法的優勢是對類實現的接口提供了文檔說明,若是須要的接口未實現則會報錯。缺點在於不能保證類是否真正實現了接口,只知道它是否說本身實現了接口,即便代碼未將接口實現也能經過檢查,這將在代碼中留下隱患。java
鴨式辨型的意思就是,若是對象具備與接口定義的方法同名的全部方法,那麼就認爲它實現了這個接口。設計模式
// 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); ... }
ensureImplements
函數至少接受兩個參數,一個是須要檢查的對象,其他爲針對此對象須要檢查是否實現的接口。具體檢查方式則是檢查對象是否實現了接口所聲明的全部方法。函數
此方法的缺點是缺少其餘兩種方法的自我描述性,須要一個輔助類Interface
和一個輔助函數ensureImplements
。而且它只關心方法名稱而不檢查參數名稱、數目、類型等。ui
Interface
類綜合第一及第三種接口實現方式,Interface
類的定義能夠爲:this
// 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 methods = 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."); } } } };
如下的設計模式依賴接口
1. 工廠模式 保證生產出來的對象實現了必須的方法。
2. 組合模式 將對象羣體與組成對象同等對待。
3. 裝飾者模式 透明地爲另外一對象提供包裝,實現相同的接口。
4. 命令模式 全部的命令對象都實現了同一批方法。prototype