iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 16
0
Modern Web

JS Design Pattern 系列 第 16

JS Design Pattern Day16-裝飾者模式 Decorator(上)

第16天,今天聽到一句同事說的話:如果你不知道你做的選擇正不正確,那就把你做的選擇變成正確的吧。
大概是我認識他以來講過最帥的一句話

今天新主題 裝飾者模式

在程式開發中,許多時候並不希望某個類別一開始就非常龐大,一次就包含許多職責。那麼我們就可以使用裝飾者模式。裝飾者模式可以動態給某物件添加一些額外的職責,而不會影響這個類別派生的其他物件。

這次直接用裝飾者模式舉個例子。我們現在要做個飛機射擊遊戲,一開始只能發送普通飛彈,晉級的時候可以發射導彈,再升等可以發射原子彈,以傳統物件導向來做的話可以這麼做:

先做個基本飛機物件,只能發射普通子彈

var Plane = function () { };

Plane.prototype.fire = function () {
    console.log('發射普通子彈');
};

再來做個發射導彈物件,它就是一個只能發射導彈的物件,那要從誰發射呢?當然是要帶入飛機囉

var MissileDecorator = function (plane) {
    this.plane = plane;
};

MissileDecorator.prototype.fire = function () {
    this.plane.fire();
    console.log('發射導彈');
};

原子彈也是一樣道理

var AtomDecorator = function (plane) {
    this.plane = plane;
};

AtomDecorator.prototype.fire = function () {
    this.plane.fire();
    console.log('發射原子彈');
};

這時候大致完成了,現在需要實際產出一台飛機,並且把導彈與原子彈安裝上去

var plane = new Plane();
plane = new MissileDecorator(plane);
plane = new AtomDecorator(plane);

實際發射就會接續發射普通子彈、導彈與原子彈了

plane.fire();

這種物件動態增加職責的方式,並沒有真正改動到Plane物件本身,而是將它放入到另一個物件之中。因為裝飾者(AtomDecorator與MissileDecorator)與他裝飾的物件(Plane)有一致的介面,所以對使用這個物件的使用者來說是透明的,被裝飾的物件也不需要了解自己曾經被裝飾過,這樣做法可以讓我們任意套用多個裝飾物件。

而JavaScript語言其實本身動態改變物件相當容易,我們可以直接改寫物件,來換個做法改寫一下:
一樣把所有物件先做好,不一樣的是將原形類別內容改為物件

var plane = {
    fire: function () {
        console.log('發射普通子彈');
    }
};

var missileDecorator = function () {
    console.log('發射導彈');
};

var atomDecorator = function () {
    console.log('發射原子彈');
};

這時候先產生一個fire1物件內容就是原本的fire內容

var fire1 = plane.fire;

然後再將原本fire的內容覆蓋為執行fire1與導彈的內容

plane.fire = function () {
    fire1();
    missileDecorator();
};

之後原子彈的做法也是一樣

var fire2 = plane.fire;
plane.fire = function () {
    fire2();
    atomDecorator();
};

plane.fire();

今天先簡單講解裝飾者模式,明天會更細部說明


上一篇
JS Design Pattern Day15-中介者模式 Mediator(下)
下一篇
JS Design Pattern Day17-裝飾者模式 Decorator(下)
系列文
JS Design Pattern 30

尚未有邦友留言

立即登入留言