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在最後一步返回產品,而抽象工廠是立即返回的。