设计模式-建造者模式
建造者模式是一种创建型的设计模式, 将一个对象的创建过程拆分成一个个小的部分, 每次决定其中的一个细节, 构建出一个复杂对象
对象的创建过程被拉长分散, 可能会经历一系列的复杂决策, 最终才会形成我们需要的对象
对象拥有多个参数, 或者拥有包含多个参数的构造函数, 通过建造者模式可以相对自由地构造对象
建造者模式的作用
- 通过拆分对象的创建步骤, 降低对象的构建复杂度, 使用者并不需要知道复杂对象的所有创建细节
- 由于拆分了对象的创建步骤, 可以有效降低构造对象时的心智负担
- 拆分出的建造者可以重复使用, 大大提高了代码的复用性
建造者模式适用于什么场景
当一个类的构造函数中有多个参数(一般大于四个), 并且这些参数中有些必填, 有些非必填时, 使用建造者模式可以降低心智负担
例如需要创建一个角色, 这个角色有参数 姓名
职业
武器
防具
力量
智力
等级
等参数, 除了姓名
之外的所有参数都是可选的
这种情况下使用建造者模式, 可以通过 角色建造者
类来一步一步设置这些参数, 最后调用 创建角色
方法生成角色对象
传统建造者模式的类图
---
title: 建造者模式
---
classDiagram
Item <|-- Weapon
Item <|-- Armor
Profession <|-- Mage
Weapon <|-- Staff
Weapon <|-- Buckler
Armor <|-- Hood
Armor <|-- Leather
Armor <|-- Belt
CharacterDirector ..> Builder
MageBuilder --|> Builder
Character <.. Builder
Character <.. MageBuilder
Character -- CharacterDirector
class Builder{
# Character character
+ SetName(string)
+ SetProfession()
+ AddWeapon()
+ AddArmor()
+ AddStrenght()
+ AddIntelligence()
+ GetCharacter(): Character
}
class MageBuilder{
# Character character
+ SetName(string)
+ SetProfession()
+ AddWeapon()
+ AddArmor()
+ AddStrenght()
+ AddIntelligence()
+ GetCharacter(): Character
}
class Character{
+ string Name
+ Profession Profession
+ Weapon[] Weapons
+ Armor[] Armors
+ int Strength
+ int Intelligence
}
class CharacterDirector{
+ Build(Builder): Character
}
class Item{
+ Buff(Character)
}
class Weapon{
+ Buff(Character)
}
class Staff{
+ Buff(Character)
}
class Buckler{
+ Buff(Character)
}
class Armor{
+ Buff(Character)
}
class Hood{
+ Buff(Character)
}
class Leather{
+ Buff(Character)
}
class Belt{
+ Buff(Character)
}
class Profession{
+ string Name
}
class Mage{
+ string Name
}
代码
定义我们需要构造的 Character
// 首先构造法师职业
public abstract class Profession
{
public string Name { get; set; }
}
public class Mage : Profession
{
public Mage()
{
Name = "法师";
}
}
// 其次定义装备, 每个不同的装备可以给任务提供不同的Buff加成
public abstract class Item
{
public abstract void Buff(Character character);
}
public abstract class Weapon : Item { }
public abstract class Armor : Item { }
public class Staff : Weapon
{
public override void Buff(Character character)
{
character.Intelligence += 10;
}
}
public class Buckler : Weapon
{
public override void Buff(Character character)
{
character.Intelligence += 2;
character.Strength += 5;
}
}
public class Hood : Armor
{
public override void Buff(Character character)
{
character.Intelligence += 5;
character.Strength += 5;
}
}
public class Leather : Armor
{
public override void Buff(Character character)
{
character.Intelligence += 2;
character.Strength += 15;
}
}
public class Belt : Armor
{
public override void Buff(Character character)
{
character.Intelligence += 15;
character.Strength += 15;
}
}
// 最后是一个简单的角色人物
public class Character
{
public Character() { }
public Character(Character character)
{
Name = character.Name;
Profession = character.Profession;
Weapons = character.Weapons;
Armors = character.Armors;
Strength = character.Strength;
Intelligence = character.Intelligence;
}
public string Name { get; set; }
public Profession Profession { get; set; }
public List<Weapon> Weapons { get; set; }
public List<Armor> Armors { get; set; }
public int Strength { get; set; }
public int Intelligence { get; set; }
}
然后定义人物的建造者 builder
public abstract class Builder
{
protected Character character;
public abstract Builder SetName(string name);
public abstract Builder SetProfession();
public abstract Builder AddWeapon();
public abstract Builder AddArmor();
public abstract Builder AddStrength();
public abstract Builder AddIntelligence();
public abstract Character GetCharacter();
}
public class MageBuilder : Builder
{
public MageBuilder(string name = null)
{
character = new Character();
SetName(name).SetProfession();
}
public override Builder AddArmor()
{
List<Armor> armors = new List<Armor> { new Hood(), new Leather(), new Belt() };
character.Armors ??= new List<Armor>();
character.Armors.AddRange(armors);
return this;
}
public override Builder AddIntelligence()
{
character.Intelligence++;
return this;
}
public override Builder AddStrength()
{
character.Strength++;
return this;
}
public override Builder AddWeapon()
{
List<Weapon> weapons = new List<Weapon> { new Staff(), new Buckler() };
character.Weapons ??= new List<Weapon>();
character.Weapons.AddRange(weapons);
return this;
}
public override Character GetCharacter()
{
var result = new Character(character);
result.Armors.ForEach(item => item.Buff(result));
result.Weapons.ForEach(item => item.Buff(result));
return result;
}
public override Builder SetName(string name)
{
character.Name = name;
return this;
}
public override Builder SetProfession()
{
character.Profession = new Mage();
return this;
}
}
最后定义一个简单的装配类, 通过builder获取character
public class CharacterDirector
{
public Character Build(Builder builder)
{
return builder
.AddWeapon()
.AddArmor()
.AddStrength()
.AddIntelligence()
.GetCharacter();
}
}
如何去使用
Builder builder = new MageBuilder();
builder.SetName("菜鸟法师");
CharacterDirector director = new CharacterDirector();
Character character1 = director.Build(builder);
// 精英法师多用点装备应该是正常的
builder.SetName("精英法师").AddIntelligence().AddStrength().AddArmor().AddWeapon();
Character character2 = director.Build(builder);
通过复用builder可以构造出不同属性的人物
简化版建造者
前面的经典版建造者模式在实际使用的时候比较繁琐, 需要经历 director --> builder --> character
下面介绍一个简化版本的建造者, 省略掉 director, 直接在 builder 里完成构建
简化版类图
---
title: 简化版建造者模式
---
classDiagram
Item <|-- Weapon
Item <|-- Armor
Profession <|-- Mage
Weapon <|-- Staff
Weapon <|-- Buckler
Armor <|-- Hood
Armor <|-- Leather
Armor <|-- Belt
MageBuilder --|> Builder
Character <.. Builder
Character <.. MageBuilder
class Builder{
# string Name
# Profession Profession
# Weapon[] Weapons
# Armor[] Armors
# int Strength
# int Intelligence
+ SetName(string)
+ SetProfession(Profession)
+ AddWeapon(Weapon)
+ AddArmor(Armor)
+ AddStrenght(int)
+ AddIntelligence(int)
+ Build(): Character
}
class MageBuilder{
# string Name
# Profession Profession
# Weapon[] Weapons
# Armor[] Armors
# int Strength
# int Intelligence
+ SetName(string)
+ SetProfession(Profession)
+ AddWeapon(Weapon)
+ AddArmor(Armor)
+ AddStrenght(int)
+ AddIntelligence(int)
+ Build(): Character
}
class Character{
+ string Name
+ Profession Profession
+ Weapon[] Weapons
+ Armor[] Armors
+ int Strength
+ int Intelligence
}
class Item{
+ Buff(Character)
}
class Weapon{
+ Buff(Character)
}
class Staff{
+ Buff(Character)
}
class Buckler{
+ Buff(Character)
}
class Armor{
+ Buff(Character)
}
class Hood{
+ Buff(Character)
}
class Leather{
+ Buff(Character)
}
class Belt{
+ Buff(Character)
}
class Profession{
+ string Name
}
class Mage{
+ string Name
}
代码
人物部分的代码不需要进行修改
只需要修改 Builder
部分, 然后移除 CharacterDirector
public class MageBuilder : Builder
{
public override Builder AddArmor(Armor armor)
{
Armors ??= new List<Armor>();
Armors.Add(armor);
return this;
}
public override Builder AddIntelligence(int intelligence)
{
Intelligence += intelligence;
return this;
}
public override Builder AddStrength(int strength)
{
Strength += strength;
return this;
}
public override Builder AddWeapon(Weapon weapon)
{
Weapons ??= new List<Weapon>();
Weapons.Add(weapon);
return this;
}
public override Builder SetName(string name)
{
Name = name;
return this;
}
public override Builder SetProfession(Profession profession)
{
Profession = profession;
return this;
}
public override Character Build()
{
var character = new Character()
{
Name = Name,
Weapons = Weapons.ToList(),
Armors = Armors.ToList(),
Profession = Profession,
Intelligence = Intelligence,
Strength = Strength,
};
Weapons.ForEach(item => item.Buff(character));
Armors.ForEach(item => item.Buff(character));
return character;
}
}
public abstract class Builder
{
protected string Name;
protected Profession Profession;
protected List<Weapon> Weapons;
protected List<Armor> Armors;
protected int Strength;
protected int Intelligence;
public abstract Builder SetName(string name);
public abstract Builder SetProfession(Profession profession);
public abstract Builder AddWeapon(Weapon weapon);
public abstract Builder AddArmor(Armor armor);
public abstract Builder AddStrength(int strength);
public abstract Builder AddIntelligence(int intelligence);
public abstract Character Build();
}
如何使用简化版建造者
Builder builder = new MageBuilder();
builder.SetName("菜鸟法师")
.SetProfession(new Mage())
.AddWeapon(new Staff())
.AddWeapon(new Buckler())
.AddArmor(new Hood())
.AddArmor(new Leather())
.AddArmor(new Belt());
var character1 = builder.Build();
builder.SetName("精英法师").AddStrength(100).AddIntelligence(100);
var character2 = builder.Build();