【設計模式】建造者模式 (Builder)

定義


將一個複雜對象的構建與它的表示分離,使得同樣的構造過程可以創建不同的表示。

建造者模式與工廠模式的區別


與工廠模式相比,建造者模式一般用來創建更複雜的對象,像是如果工廠模式是生產一隻滑鼠,建造者模式就是建造滑鼠的細節,像是微動開關的差異、滑鼠的材質那類的。

工廠模式是將對象的全部創建過程封裝在工廠類中,由工廠類向Client提供最終的產品,而建造者類只提供產品類中各個組件,將具體如何組裝、組裝順序交給導演(Director),然後組好的產品經由導演(Director)交給Client。

建造者UML圖

  • Product - 產品類:產品的抽象類,可以再實作有哪些產品
  • Builder -抽象類,規範產品的組建,一般是由子類實現具體的組件過程。
  • ConcreteBuilder–因為每個建造的細節可能不一樣,所以實作Builder來做不同的建造細節
  • Director - 導演,指揮組件該如何組起來

應用


這邊以創建角色為例,分為怪物跟NPC兩種的角色,兩個種類都會有武器、角色模型、角色的AI,兩種角色共同要設定的有要設定哪種AI、設定角色的模型、角色的武器。

創建一個共通的角色類別
1
2
3
4
5
6
7
8
9
10
11
public class ICharacter
{
public string Weapon_Name;
public string FBXModule_Name;
public string AI_Name;
}

//從角色可以衍伸各種角色實作,像是龍、NPC、貓之類的
public class Enemy_Dragran : ICharacter { }
public class NPC_Eric : ICharacter { }
public class Enemy_Cat : ICharacter { }

而共通的製造細節,就放在抽象類Builder上

1
2
3
4
5
6
7
public abstract class ICharacter_Builder
{
public abstract void AddWeapon();
public abstract void SetFBXModule();
public abstract void SetAI();
public abstract ICharacter GetResult();
}

而我們角色有分為兩種,一個是NPC跟怪物,這個具體要怎麼創建就在繼承於Builder的類上實作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Enemy_Builder : ICharacter_Builder
{
ICharacter _character;

public Enemy_Builder(ICharacter character)
{
_character = character;
}

public override void AddWeapon()
{
_character.Weapon_Name = "Enemy_Weapon";
}

public override void SetFBXModule()
{
_character.FBXModule_Name = "Enemy_FBX";
}

public override void SetAI()
{
_character.AI_Name = "Enemy_AI";
}

public override ICharacter GetResult()
{
return _character;
}
}

另外一個NPC類則是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class NPC_Builder : ICharacter_Builder
{
ICharacter _character;

public NPC_Builder(ICharacter character)
{
_character = character;
}

public override void AddWeapon()
{
_character.Weapon_Name = "NPC_Gun";
}

public override void SetFBXModule()
{
_character.FBXModule_Name = "NPC_FBX";
}

public override void SetAI()
{
_character.AI_Name = "NPC_AI";
}

public override ICharacter GetResult()
{
return _character;
}
}

在最後,交由一個導演(Director)來指示角色是如何被組起來的

1
2
3
4
5
6
7
8
9
10
public class CharacterBuilderDirector
{
public static ICharacter Construct(ICharacter_Builder builder)
{
builder.AddWeapon();
builder.SetFBXModule();
builder.SetAI();
return builder.GetResult();
}
}

現在有一個客戶(client)需要創建怪物的角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Client : MonoBehaviour
{

void Start()
{
ICharacter character = new Enemy_Cat();
ICharacter_Builder builder = new Enemy_Builder(character);

ICharacter Instance = CharacterBuilderDirector.Construct(builder);

Debug.Log(Instance.AI_Name); //看一下創建出來的AI名稱
Debug.Log(Instance.FBXModule_Name);
Debug.Log(Instance.Weapon_Name);
}
}

看起來就會像是這個樣子

對應最上面的建造者模式的關係

ICharacter : Poduct

ICharacter_Builder : Builder抽象類

Enemy_Builder :Builder抽象類的實作

NPC_Builder:Builder抽象類的實作

CharacterBuilderDirector :Director