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