Skip to content

建造者模式

将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。

适合的场景

有些对象不是 new 一下就完事了,比如:

  • RPG角色:职业、属性、装备、技能全都不同

  • 游戏剧情事件:同样的事件框架,不同剧情内容

如果你每次都手动一个个设置字段、判断状态,代码就会很难维护; 建造者模式让你「按步骤、按顺序」拼装对象,既灵活又有条理

  • 创建流程固定但步骤多的复杂对象

  • 不同版本/类型的对象有相同建造过程但不同内容

  • 希望通过链式调用、分步组装提高代码可读性和复用性

基本结构

  1. 产品类(Product):被创建的复杂对象

  2. 抽象建造者(Builder):定义构建方法

  3. 具体建造者(ConcreteBuilder):实现这些方法

  4. 指挥者(Director,可选):负责控制构建顺序

示例

csharp
// 产品
public class Character
{
    public string Class;
    public string Weapon;
    public string Armor;

    public void Show()
    {
        Console.WriteLine($"职业: {Class}, 武器: {Weapon}, 盔甲: {Armor}");
    }
}

// 抽象建造者
public interface ICharacterBuilder
{
    void SetClass();
    void SetWeapon();
    void SetArmor();
    Character GetResult();
}

// 具体建造者:战士
public class WarriorBuilder : ICharacterBuilder
{
    private Character _character = new Character();

    public void SetClass() => _character.Class = "战士";
    public void SetWeapon() => _character.Weapon = "大剑";
    public void SetArmor() => _character.Armor = "重甲";
    public Character GetResult() => _character;
}

// 指挥者
public class CharacterDirector
{
    private ICharacterBuilder _builder;

    public CharacterDirector(ICharacterBuilder builder)
    {
        _builder = builder;
    }

    public Character Build()
    {
        _builder.SetClass();
        _builder.SetWeapon();
        _builder.SetArmor();
        return _builder.GetResult();
    }
}

// 使用
var builder = new WarriorBuilder();
var director = new CharacterDirector(builder);
var character = director.Build();
character.Show();

有时候我们会去掉 Director,让 Builder 自己负责整个流程, 还能支持链式调用

c#
// 抽象建造者
public interface ICharacterBuilder
{
    ICharacterBuilder SetClass();
    ICharacterBuilder SetWeapon();
    ICharacterBuilder SetArmor();
    Character GetResult();
}

// 具体建造者:战士
public class WarriorBuilder : ICharacterBuilder
{
    private Character _character = new Character();

    public ICharacterBuilder SetClass()
    {
        _character.Class = "战士";
        return this;
    }
    public ICharacterBuilder SetWeapon()
    {
        _character.Weapon = "大剑";
        return this;
    }
    public ICharacterBuilder SetArmor()
    {
        _character.Armor = "重甲";
        return this;
    }
    public Character GetResult() => _character;
}

GDScript 示例

gdscript
# 产品类
class Character:

    var job := ""
    var weapon := ""
    var armor := ""

    func show():
        print("职业: %s, 武器: %s, 盔甲: %s" % [job, weapon, armor])

# 建造者基类
class CharacterBuilder:
        func set_job(): pass
        func set_weapon(): pass
        func set_armor(): pass
        func get_result() -> Character: return null

# 具体建造者:骑士
class KnightBuilder extends CharacterBuilder:
        var _char = Character.new()

        func set_job(): _char.job = "骑士"
        func set_weapon(): _char.weapon = "长枪"
        func set_armor(): _char.armor = "银甲"
        func get_result() -> Character: return _char

# 指挥者(可选)
class CharacterDirector:
        func build(builder: CharacterBuilder) -> Character:
                builder.set_job()
                builder.set_weapon()
                builder.set_armor()
                return builder.get_result()
# 使用
func _ready():
    var builder = KnightBuilder.new()
    var director = CharacterDirector.new()
    var knight = director.build(builder)
    knight.show()