Java設計模式之從[魔獸世界副本]分析原型(Prototype)模式

  “副本”是網絡遊戲任務的一種形式,它最初出現於無盡的任務,現在運用得最有名的就是魔獸世界的副本了,我們將它稱爲副本任務。副本任務一般是一個隊伍的人一起闖關的,假設有隊伍A、隊伍B、隊伍C,分別對同一個副本任務發出挑戰,他們在副本任務中的行爲是不相干的。也就是說,A隊伍在副本任務中消滅boss、開啓寶箱,不會對B、C兩支隊伍造成任何影響,B、C同理。因此,“副本”可以理解成,從任務的原型中拷貝,然後給不同的隊伍去執行。

  現在從“原型模式”來思考一下副本的實現(真正的魔獸世界是如何實現的我不知道)。原型模式的意圖是從原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。以魔獸世界中的“死亡礦井”副本爲例,它是一個最基本的副本,玩家達到10級就可以接受此副本任務。爲了簡化模型,我把副本任務的屬性分爲任務名、敵人數量和難度等級。若玩家進入了一個副本任務,遊戲則先會尋找這個副本任務的原型(也就是一個對象),接下來把這個對象複製(clone)一次,再把複製好的對象返回給玩家,告訴玩家:你的副本任務我已經複製好了,由於是從原型中拷貝下來的,所以你在這個任務裏怎麼樣都不會影響到別人。

  以下是Java代碼:

interface Cloneable{
    Object clone();
}

class Deadmines implements Cloneable {
    String mapName = "死亡礦井";
    int enemies ;
    int difficulty ;
    public Deadmines(int _difficulty, int _enemies){
        difficulty = _difficulty;
        enemies = _enemies;
    }
    public Object clone(){
        return new Deadmines(difficulty, enemies);
    }
    public void print(){
        System.out.printf("副本名: %s, 敵人數目: %d, 難度: %d\n", mapName, enemies, difficulty); 
    }
}

class Prototype
{
    public static void main(String[] args) {
        Deadmines deadminesPrototype = new Deadmines(10, 200);
        Deadmines playerDeadmines = (Deadmines)deadminesPrototype.clone();
        playerDeadmines.print();
        System.out.println(deadminesPrototype == playerDeadmines);
    }
}

輸出結果:

副本名: 死亡礦井, 敵人數目: 200, 難度: 15
false

  稍微說明一下。main方法中的最後一行是用於判斷原型和副本是否爲同一引用,結果顯然是false,因爲副本是被拷貝出來的,並不是直接返回原型。通俗地來講,原型模式就是以一個對象爲模板,來構造與它一樣的對象。它可以隱藏具體的克隆細節(如我們在使用時只需要調用clone方法,而不需要知道它是怎麼clone的)。

  另外還要提到的是,在Java中本身就存在Cloneable接口,在上例中我們是自己重新定義了一個Cloneable。另外,Object類中本身也有一個受保護的方法clone,它可用於改寫。在Java文檔中寫道,Object的clone方法沒有繼承Cloneable接口,如果直接調用,則會觸發CloneNotSupportedException異常。能夠調用clone方法的對象一定要繼承Cloneable接口。(CloneNotSupportedException - if the object's class does not support the Cloneable interface. Subclasses that override the clone method can also throw this exception to indicate that an instance cannot be cloned.)

  總結一下,當一個系統應該獨立於它產品創建、構成時、實例化的對象是運行時加載(如副本任務)時、爲了避免創建一個與產品類層次平行的工廠類層次時、當一個類的實例只能有幾個不同狀態組合中的一種時,可以考慮使用原型模式。它在Java、C#中得到了廣泛的應用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章