Think in ActionScript 3.0Ⅲ -電腦資料

電腦資料 時(shí)間:2019-01-01 我要投稿
【clearvueentertainment.com - 電腦資料】

8.面向?qū)ο蟪绦蛟O(shè)計(jì)

8.1類和對象的概念

類:類是用來創(chuàng)建同 一類型的對象的“模板”,在一個(gè)類中定義了該類對象所應(yīng)具有的成 員變量以及方法,

Think in ActionScript 3.0Ⅲ

。

對象:對象是類的實(shí)例。

8.2類之間的關(guān)系

系統(tǒng)中的類有那些關(guān)系:依賴、關(guān)聯(lián)(聚合、合成)、泛化、實(shí)現(xiàn)。

1.依賴:對于外部類或?qū)ο蟮囊茫?/p>

5.關(guān)聯(lián):關(guān)聯(lián)暗示兩個(gè)類在 概念上位于相同的級別;

6.聚合:表示一種“擁有”關(guān)系,是 兩個(gè)類之間一種整體 / 局部的關(guān)系;

7.合成:表示一種更強(qiáng)“擁有 ”關(guān)系,就像人和腿的關(guān)系一樣。組合而成的新對象對組成部分的內(nèi)容分配 和釋放有絕對責(zé)任;

8.泛化:表現(xiàn)為繼承 extends;

9.實(shí)現(xiàn):表 現(xiàn)為實(shí)現(xiàn) implements。

8.3 面向?qū)ο蟪绦蛟O(shè)計(jì)(OOP)

在面向?qū)?象出現(xiàn)以前,結(jié)構(gòu)化程序設(shè)計(jì)是程序設(shè)計(jì)的主流,結(jié)構(gòu)化程序設(shè)計(jì)又稱為面向過 程的程序設(shè)計(jì)。這種設(shè)計(jì)方法開發(fā)的軟件穩(wěn)定性、可修改性和可重用性都比較差 。

與過程相比對象是穩(wěn)定的。面向?qū)ο蟮能浖到y(tǒng)是由對象組成的,復(fù)雜 的對象是由比較簡單的對象組合而成的。也就是說,面向?qū)ο蠓椒▽W(xué)使用對象分 解取代了傳統(tǒng)的功能分解。

面向?qū)ο蟮木柙谟诳紤]問題的思路是從現(xiàn)實(shí) 世界人類思維習(xí)慣出發(fā)的,只要領(lǐng)會了這一點(diǎn),就領(lǐng)會了面向?qū)ο蟮乃季S方法。 萬事萬物皆為對象,大至日月星辰,小至沙粒微塵,都是對象。對象包容了一切 事物,不僅僅是那些看得見摸得著的是實(shí)體,如:地球、汽車、樹葉,還包括那 些客觀存在的事物,如:社會、互聯(lián)網(wǎng)、朋友圈子等等,包羅萬象。

以開 車為例,用面向過程的思想去考慮,那么你先得知道怎么啟動(dòng),怎么踩油門,怎 么掛檔。這些應(yīng)該是司機(jī)的活,你要把這些步驟都實(shí)現(xiàn)出來。如果用面向?qū)ο蟮?思想,把自己看成領(lǐng)導(dǎo),只需要下達(dá)命令,告訴它你要去哪里就行了(例如,調(diào) 用drive() 方法),具體怎么開,怎么踩油門,怎么掛檔,不需要我們?nèi)ス堋?/p>

那么 dirve() 這個(gè)方法放到車?yán)锸欠窈线m呢,是不是應(yīng)該放到“司 機(jī)”類更合理呢?封裝是很靈活的,沒有對與錯(cuò)之分,只有好與更好,需要 具體問題具體分析。因?yàn)?dirve() 方法要用到油門和車檔,而這些東西都在車?yán)?面,因此如果將它封裝到車這個(gè)類里面可能更好些。

下面我們通過對比面 向過程和面向?qū)ο蟮脑O(shè)計(jì)方式體會什么才是面向?qū)ο蟮乃季S。

8.4 出圈游 戲 —— 面向過程 VS 面向?qū)ο?/p>

8.4.1 游戲規(guī)則

假設(shè) 有5 個(gè)小孩兒手拉手圍成一圈。從第一個(gè)小孩兒開始以順時(shí)針方向依次報(bào)數(shù) —— “1,2,3”,報(bào) 3的人出列,第四個(gè)人從1 開始重 新報(bào)數(shù),報(bào)到 3 時(shí)再出列。如此下去,直到所有人全部出列為止,要求按照出列 的順序輸出他們的序號。

下面來看圖理解,首先有5 個(gè)小孩圍成一個(gè)圈:

圖一、 5 個(gè)小孩兒圍成一圈

圖二、數(shù)到 3的小孩兒退出去

圖三、再從2 號開始數(shù)三個(gè)人, 5 號退出,然后是2 號,最后是4 號。

最終輸出的順序應(yīng)該是3、1、5、2、4。

8.4.2 出圈游戲 —— 面向過程(cirgame/ CircleGame1.as)

下面用面向過程的思想寫這個(gè)程 序,通過讀注釋先來看一下這個(gè)程序:

//有5 個(gè)小孩兒圍成的圈
var array:Array = new Array(5);
for (var i = 0; i < array.length; i++) {
    // 如果元素值為 true 表示他在圈內(nèi),如果是false 表示不在圈內(nèi)
    array[i] = true;
}

// 圈內(nèi)還剩多少人,最開始人都在,等于 array.length
var leftCount:int = array.length;
// 當(dāng)前所報(bào)的數(shù),初始為 0
var countNum:int = 0;
// 圈子的數(shù)組下標(biāo),表示當(dāng)前指向的是誰
var index:int = 0;

while(leftCount > 0) {
    if (array[index] == true) {
        // 如果當(dāng)前這個(gè)人在圈內(nèi)則報(bào)數(shù)
        countNum++;
        if (countNum == 3) {
            // 如果所報(bào)的數(shù)是3 則出列,剩余人數(shù)減1,并且下一 次從新開始報(bào)數(shù)
            trace("out " + (index + 1));
            array[index] = false;
            leftCount--;
            countNum = 0;
        }
    }

    //數(shù)組下標(biāo)增加
    index++;
    if (index == array.length) {
        // 如果下標(biāo)是最后一個(gè)位則歸 0,因?yàn)檫@個(gè)圈是圓的
        index = 0;
    }
}

用array數(shù)組代表這個(gè)圍成的圈,開始讓圈數(shù)組中的每個(gè)元素都 為 true,表示它們都在圈內(nèi),如果設(shè)為 false 則表示不在圈內(nèi),后面報(bào)數(shù)的時(shí) 候就不予考慮了。

接下來定義三個(gè)變量分別表示圈內(nèi)還剩多少人,所報(bào)的 數(shù)是多少和數(shù)組下標(biāo)。

下面 while 循環(huán)開始,只有圈內(nèi)還有人 (leftCount > 0)就進(jìn)行循環(huán),首先判斷當(dāng)前 index 所指的元素是否為真, 如果是則報(bào)數(shù)加 1,再判斷是不是加到 3 了,如果是則打印出當(dāng)前的數(shù)組下標(biāo), 再將該元素設(shè)為 false,剩余人數(shù)減1,下一次從新開始報(bào)數(shù),

電腦資料

Think in ActionScript 3.0Ⅲ》(http://clearvueentertainment.com)。

最后讓數(shù)組下標(biāo)加 1,當(dāng)指到最后時(shí),將數(shù)組下標(biāo)置為 0,因?yàn)檫@是一個(gè)圈, 要用循環(huán)的數(shù)組來表示。

8.4.3 出圈游戲 —— 面向?qū)ο?(cirgame/ CircleGame2.as)

回顧上一個(gè)例子,在面向過程的程序中, 明明是圍成的一個(gè)圈兒,卻要看成是一個(gè)數(shù)組;明明是一個(gè)個(gè)小孩兒卻要看成是 數(shù)組的一個(gè)個(gè)元素。這不就是為了讓計(jì)算機(jī)看懂嗎?但是,面向?qū)ο笫歉咏咏?人類的思維模式,我們在現(xiàn)實(shí)中看到的就是一個(gè)個(gè)小孩兒,怎么能說是數(shù)組?那 么這一個(gè)個(gè)小孩兒就是一個(gè)個(gè)對象,他們都是Kid。圍成的這個(gè)圈,就是一個(gè) KidCircle。很自然吧,比大自然還自然!下面來體會面向?qū)ο蟮脑O(shè)計(jì)思想:

package cirgame {
    public class CircleGame2 {
        public function CircleGame2() {
            var kc:KidCircle = new KidCircle(5);
            var countNum:int = 0;
            var k:Kid = kc.head;

            while (kc.count > 0) {
                countNum++;
                if (countNum == 3) {
                    trace(k.id + 1);
                    kc.remove(k);
                    countNum = 0;
                }
                k = k.right;
            }

        }
    }
}

// 每個(gè)Kid都有自己的id,并且左右手還拉著其它的Kid
class Kid {
    var id:uint;
    var left:Kid;
    var right:Kid;
}

// 這個(gè)圈子里可以加入或移除一些Kid
class KidCircle {
    var count:uint = 0;
    var head:Kid;
    var rear:Kid;

    function KidCircle(n:uint) {
        for (var i = 0; i < n; i++) {
            var kid:Kid = new Kid();
            add(kid);
        }
    }

    function add(kid:Kid):void {
        kid.id = count;
        if (count == 0) {
            head = kid;
            rear = kid;
            kid.left = kid;
            kid.right = kid;
        } else {
            rear.right = kid;
            kid.left = rear;
            kid.right = head;
            head.left = kid;
            rear = kid;
        }
        count++;
    }

    function remove(kid:Kid):void {
        if (count <= 0) {
            return;
        } else if (count == 1) {
            head = rear = null;
        } else {
            kid.left.right = kid.right;
            kid.right.left = kid.left;
            if (kid == head) {
                head = kid.right;
            } else if (kid == rear) {
                rear = kid.left;
            }
        }
        count--;
    }
}

這段程序中設(shè)計(jì)了兩個(gè)類,代表兩類客觀事物 —— 小孩(Kid)和圈子(KidCircle)。從8.4.1的圖中可以確切地看到。Kid有三個(gè) 屬性:id 號、左手和右手,左手拉著一個(gè)Kid,右手拉著一個(gè)Kid,因此left和 right存放兩個(gè)Kid的引用。

下面是KidCircle類,代表圍成的圈子,這個(gè)圈子可以加入或移除一些Kid,因 此有add和remove兩個(gè)方法。head和rear兩個(gè)成員變量用于指向隊(duì)首和隊(duì)尾的兩個(gè) Kid,因?yàn)樾┨砑拥腒id 要放在隊(duì)尾(rear)的后面,因?yàn)檫@是一個(gè)圈子,所以還 需要讓隊(duì)尾的小孩兒拉住隊(duì)首(head)的小孩兒,因此需要保存這兩個(gè)成員變量 。

最后是測試類,主要的邏輯和前一個(gè)例子比較像,這里就不多解釋了。

通過這個(gè)例子大家可以看出,我們無形之間就完成了一個(gè)數(shù)據(jù)結(jié)構(gòu) —— 雙向循環(huán)鏈表。而前面面向過程的例子,實(shí)際上就是一個(gè)順序的 存儲結(jié)構(gòu) —— 線性表。

后面,我會帶大家寫一個(gè)貪吃蛇的游 戲,目的是學(xué)習(xí)面向?qū)ο缶幊痰乃枷耄ú⒎窃撚螒虮旧恚,在貪吃蛇中我們就?運(yùn)用到類似于單向鏈表的結(jié)構(gòu),如果雙向鏈表掌握了,那么單向一定沒問題。

通過本節(jié)請大家認(rèn)真體會面向?qū)ο蟮脑O(shè)計(jì)思想。一次學(xué)會,終身受用。

最新文章