JavaScript重構(七):重用老代碼

在Java中,有這樣一段老代碼:
Java代碼 
class Round{  
  public void drawRound(); //畫圓  

 
現在新代碼希望能和它共存,使用一個Person的對象來控制,隻不過,可能drawRound,也可能drawRect啊:
Java代碼 
class Rect{  
  public void drawRect(); //畫方  

 
好,廢話少說,我先想到瞭Adapter模式:
Java代碼 
interface Drawable{  
  public void draw();  
}  
 
public class RoundAdapter implements Drawable{  
  private Round round;  
  public void draw(){  
    round.drawRound();  
  }  
}  
 
public class RectAdapter implements Drawable{  
  private Rect rect;  
  public void draw(){  
    rect.drawRect();  
  }  

 
然後,我再引入一個Person對象,就能搞定這一切瞭:
Java代碼 
class Person{  
  private Drawable adapter;  
  public Person(Drawable adapter){  
    this.adapter = adapter;  
  }  
  public void draw(){  
    this.adapter.draw();  
  }  
}  
 
  Drawable rou = new RoundAdapter();  
  Drawable rec = new RectAdapter();  
  new Person(rou).draw(); //畫圓 
  new Person(rec).draw(); //畫方 
 
想必到此已經讓你煩瞭,一個Adapter模式的最簡單例子。再多看一看,這個模式的核心是什麼?接口!對,正是例子中的Drawable接口——正是在接口的規約和領導下,我們才能讓畫圓和畫方都變得那麼聽話。
 
現在JavaScript中,也有這樣一段老代碼:
Java代碼 
function Round(){  
  this.drawRound = function(){  
    alert("round");  
  }  

 
我也想依葫蘆畫瓢,但是JavaScript沒有接口瞭,怎麼辦?
……
接口的作用是什麼?是對類的行為的規約,可是JavaScript的行為是動態的,無法用簡單純粹的接口來實現、來約束,即便模擬出這樣一個接口(參見《JavaScript Design Pattern》),在此又有必要使用它麼?強行做出一個接口來,這不是和JavaScript的初衷相違背瞭嗎?
再回到這個問題上面,我原本希望Person的對象可以調用一個統一的draw方法,隻是在通過構造Person對象的時候,傳入一個不同實現的Drawable對象,做出瞭不同約束下的實現。
那麼,JavaScript中,不僅僅方法的調用者可以作為一個參數傳入,方法本身也可以作為參數傳入(即所謂方法閉包),這樣,所有變化點都控制在這個參數之中,不也實現瞭我想要的接口規約的效果嗎:
Java代碼 
function Rect(){  
  this.drawRect = function(){  
    alert("rect");  
  }  
}  
 
function Person(obj){  
//obj參數的格式:{doWhat,who}  
  for(var i in obj){  
    this.doWhat = i;  
    this.who = obj[i];  
    break;  
  }  
  this.draw = function(){  
    this.who[this.doWhat].call(this.who);  
  };  
}  
 
var rou = { drawRound : new Round() };  
var rec = { drawRect : new Rect() };  
(new Person(rou)).draw();  
(new Person(rec)).draw(); 
 
 
寫到這裡,我覺得很開心:
在Java中,通過接口的規約和適配器的幫助,我將變化點封裝在Person構造器的參數之中;
JavaScript中,沒有瞭接口、脫離瞭適配器的幫助,我依然能將變化點封裝在Person的構造器參數之中。

作者“四火的BLOG”
 

發佈留言