使用javascript更精確試作decorator pattern

 Wed, 13 Jun 2007 23:14:40 +0800

我在前幾篇文章裡面試做decorator pattern(用javascript試作decorator),但是總覺得不滿意,所以再試著弄更清楚。

幾個不清楚的地方是,我沒有嚴格地按照GoF的方式做,因為原本只是想初步達到效果(利用constructor彈性地賦予職責),但是class的關係不太明顯,說是decorator pattern有一點勉強,所以這一次再加強一下。

大致想做到幾點要求:

  1. decorator與被裝飾的對象,繼承同一個上層類別(觀念是這樣啦,但是用javascript實作其實感覺......類別關係不那麼強,沒辦法,先求有)
  2. 同樣用constructor可以動態賦予更多裝飾效果(職責)

程式很簡單,有一個最頂層的function叫做man,youngman跟decorator直接繼承man,singer跟conductor繼承decorator。youngman的shout方法會印出"I'm a young man"訊息,使用singer及conductor時則會為youngman加上"I'm a singer too."以及"I'm a conductor too."訊息。

function man () {
this.shout = function () {
}
}
function youngman () {
this._init = man;
this._init();
this._msg = "I'm a young man.";
this.shout = function () {
alert(this._msg);
}
}
youngman.prototype = new man;
function decorator (obj) {
this._init = man;
this._init();
this._obj = obj;
this.shout = function () {
}
}
decorator.prototype = new man;
function singer (obj) {
this._init = decorator;
this._init(obj);
this._msg = " I'm a singer too.";
this.shout = function () {
this._obj._msg += this._msg;
this._obj.shout();
}
}
singer.prototype = new decorator;
function conductor (obj) {
this._init = decorator;
this._init(obj);
this._msg = " I'm a conductor too.";
this.shout = function () {
this._obj._msg += this._msg;
this._obj.shout();
}
}
conductor.prototype = new decorator;

測試了一下:

var tmp1=new youngman();
tmp1.shout();
//印出"I'm a young man."
var tmp2=new singer(new youngman());
tmp2.shout();
//印出"I'm a young man. I'm a singer too."
var tmp3=new conductor(new youngman());
tmp3.shout();
//印出"I'm a young man. I'm a conductor too."
var tmp4=new conductor(new singer(new youngman()));
tmp4.shout();
//印出"I'm a young man. I'm a singer too. I'm a conductor too."

大概就是這樣了吧?希望沒大錯。

今天又看到一個有趣的想法,就是用類似的方式來做AOP,有空再來研究看看。(可以參考這篇blog文章:The Decorator Pattern for JavaScript