Javascript 設計模式讀書筆記(一)——接口

Javascript 中模仿接口的三種方法

1. 註釋描述

/*

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

2. 屬性檢查

/*

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

3. 鴨式辨型

鴨式辨型的意思就是,若是對象具備與接口定義的方法同名的全部方法,那麼就認爲它實現了這個接口。設計模式

// 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

相關文章
相關標籤/搜索