1. 程式人生 > >Java設計模式之從[Dota的武器建立]分析生成器(Builder)模式

Java設計模式之從[Dota的武器建立]分析生成器(Builder)模式

  Dota可謂是當下最流行的遊戲之一,玩家分為兩隊,分別是天輝(近衛)和夜魘(天災),每隊5個人,通過補刀、殺敵獲取經驗和金錢,金錢可用來購買強大的武器,最終推倒敵方基地則獲勝。我們現在考慮一個最簡單的武器組成元素:武器是由武器名、攻擊力、武器顏色組成,我們要想辦法實現能夠新建各種各樣武器的一個模式。假設我們預設了兩種武器,分別是聖劍(攻擊力300,黃色)、聖者遺物(攻擊力60,藍色),我將試著用生成器模式來做一個武器的生成小框架。

  生成器模式的意圖是將一個複雜物件與它的表示分離,使得同樣的構建過程可以建立不同的表示。

  我們將生成武器的抽象過程提取出來: 定義一個武器基類,包含武器名、攻擊力、顏色,以及列印武器資訊的方法;然後我們通過為武器命名並賦予攻擊力值、顏色來完成一個武器的生成,最後將生成的武器返回。Java程式碼如下:

class Weapon{
    private String color;
    private String name;
    private int attack;
    public String getName(){
        return name;
    }
    public int getAttack(){
        return attack;
    }
    public String getColor(){
        return color;
    }
    public void setAttack(int _attack){ attack = _attack;}
    public void setName(String _name){ name = _name;}
    public void setColor(String _color){ color = _color;}

    public void print(){
        System.out.printf("武器名: %s, 攻擊力: %d, 顏色: %s\n", name, attack, color);
    }
}

interface WeaponBuilder {
    void buildBasicInformation();
    void buildColor();
    Weapon getWeapon();
}

class Weapons
{
    public static void build(WeaponBuilder builder){
        builder.buildBasicInformation();
        builder.buildColor();
    }
}

class DivineRapierBuilder implements WeaponBuilder{
    private Weapon weapon = new Weapon();
    public void buildBasicInformation(){
        weapon.setName("聖劍");
        weapon.setAttack(300);
    }
    public void buildColor(){
        weapon.setColor("黃色");
    }
    public Weapon getWeapon(){
        return weapon;
    }
}

class SacredRelicBuilder implements WeaponBuilder{
    private Weapon weapon = new Weapon();
    public void buildBasicInformation(){
        weapon.setName("聖者遺物");
        weapon.setAttack(60);
    }
    public void buildColor(){
        weapon.setColor("藍色");
    }
    public Weapon getWeapon(){
        return weapon;
    }
}

class Builder
{
    public static void main(String[] args) {
        WeaponBuilder divineRapierBuilder = new DivineRapierBuilder();
        Weapons.build(divineRapierBuilder);
        WeaponBuilder sacredRelicBuilder = new SacredRelicBuilder();
        Weapons.build(sacredRelicBuilder);
        Weapon divineRapier = divineRapierBuilder.getWeapon();
        Weapon sacredRelic = sacredRelicBuilder.getWeapon();
        divineRapier.print();
        sacredRelic.print();
    }
}

輸出結果為:

武器名: 聖劍, 攻擊力: 300, 顏色: 黃色
武器名: 聖者遺物, 攻擊力: 60, 顏色: 藍色

  下面簡要來分析一下上面的程式碼。Weapon類是記錄武器資訊的一個類,我們最終就是要返回一個我們需要的Weapon物件。這個Weapon物件是一個比較複雜的物件,它由名稱和攻擊力兩個部分組成,我們把生成一個武器的必要方法宣告在WeaponBuilder介面中,接下來為聖劍、聖者遺物兩個武器實現方法(分別是DivineRapierBuilder類和SacredRelicBuilder類)。最後,我們定義一個製造武器的類Weapons,裡面的靜態方法build傳入了一個WeaponBuilder物件,它會呼叫此物件的build,並返回getWeapon作為結果。如main方法中所寫的那樣,我們總是可以呼叫Weapons.build來建立一個新的武器,Weapons本身並不建立武器,主要依靠的是傳入的WeaponBuilder來建立。如果我們需要建立一個新武器,我們只需要構造一個繼承了WeaponBuilder介面的類即可。

  在設計模式一書中談到,抽象工廠模式與Builder模式類似,都可以建立複雜物件;區別是Builder模式著重於一步步構造一個複雜物件,而抽象工廠著重於多個系列產品物件的建立(如上一篇部落格的ProduceMarine、ProduceFirebat等),Builder在最後一步返回產品,而抽象工廠是立即返回的。