还是咋们的电脑店,不过今天的客户有点不同寻常。还记得上次那个我们给装了9900K CPU的客户吗?没错,今天他又来了。但是今天他的需求有点不同寻常,他要装300套和之前配置一样的电脑,用来开一个巨豪华的网咖。对于我们来说当然高兴呀,而且这生意可不能黄了。但是单单靠我们几个人肯定不行呀,等装完300台电脑,黄花菜都凉了。
于是我们请了两个经验丰富的临时工来帮我们组装一下。那么问题就来了,临时工他们两个人的装配顺序不一样,每个人有每个人的工作习惯,但是肯定要按照客户的要求,按照之前配置来装电脑呀。于是我们就做出规定,对于电脑配件的装配顺序可以不一样,但是要安装的配件必须是我们列出来的。
既然如此,我们就先把模板制定出来:
public abstract class IComputerDiy
{
private List<SequenceItem> _sequence = null;
public void SetSequence(List<SequenceItem> sequence)
{
if (sequence == null || sequence.Count == 0)
{
throw new Exception("一定要按照步骤来,虽然我不管你的步骤是什么样的。");
}
if(sequence.Count != 5)
{
throw new Exception("不能漏掉任何一步哦。");
}
this._sequence = sequence;
}
/// <summary>
/// 组装的电脑肯定要能给跑起来才是一台合格的电脑
/// </summary>
public void Run()
{
foreach (var item in _sequence)
{
switch (item)
{
case SequenceItem.POWER:
this.AddPower();
break;
case SequenceItem.CPU:
this.AddCPU();
break;
case SequenceItem.RAM:
this.AddRAM();
break;
case SequenceItem.BOARD:
this.AddBoard();
break;
case SequenceItem.DISK:
this.AddDisk();
break;
}
}
}
/// <summary>
/// 安装电源
/// </summary>
public abstract void AddPower();
/// <summary>
/// 安装主板
/// </summary>
public abstract void AddBoard();
/// <summary>
/// 安装CPU
/// </summary>
public abstract void AddCPU();
/// <summary>
/// 安装内存条
/// </summary>
public abstract void AddRAM();
/// <summary>
/// 安装硬盘
/// </summary>
public abstract void AddDisk();
}
然后是我们要装配的产品,用Intel芯片的电脑。
/// <summary>
/// 用Intel CPU的性能很强劲的电脑
/// </summary>
public class IntelPowerfulPC : IComputerDiy
{
public override void AddBoard()
{
Console.WriteLine("我是Z390的主板,我装INTEL的CPU。");
}
public override void AddCPU()
{
Console.WriteLine("我是CPU 9900K,嗯~我很保值。");
}
public override void AddDisk()
{
Console.WriteLine("我是硬盘,我叫傲腾905p。");
}
public override void AddPower()
{
Console.WriteLine("我是电源,海韵的哦~");
}
public override void AddRAM()
{
Console.WriteLine("我是内存,32GB DDR4 4000MHZ。");
}
}
我们招聘临时工是干嘛的?帮我们组装产品的,所以我们对他们进行约束,不然他们划水了怎么办。
/// <summary>
/// 装配者
/// </summary>
public abstract class IComputerBuilder
{
public abstract IComputerDiy Product();
}
然后是我们招聘的老师傅,分别叫小明和王五,我们可以称他们为建造者:
/// <summary>
/// 我是临时工小明
/// </summary>
public class ComputerBuilderXiaoMing : IComputerBuilder
{
private readonly IComputerDiy _computer = new IntelPowerfulPC();
private void SetSequsence()
{
List<SequenceItem> sequences = new List<SequenceItem>();
sequences.Add(SequenceItem.DISK);
sequences.Add(SequenceItem.BOARD);
sequences.Add(SequenceItem.CPU);
sequences.Add(SequenceItem.RAM);
sequences.Add(SequenceItem.POWER);
_computer.SetSequence(sequences);
}
public override IComputerDiy Product()
{
SetSequsence();
return _computer;
}
}
/// <summary>
/// 我是临时工王五
/// </summary>
public class ComputerBuilderWangWu : IComputerBuilder
{
private readonly IComputerDiy _computer = new IntelPowerfulPC();
private void SetSequsence()
{
List<SequenceItem> sequences = new List<SequenceItem>();
sequences.Add(SequenceItem.BOARD);
sequences.Add(SequenceItem.CPU);
sequences.Add(SequenceItem.RAM);
sequences.Add(SequenceItem.DISK);
sequences.Add(SequenceItem.POWER);
_computer.SetSequence(sequences);
}
public override IComputerDiy Product()
{
SetSequsence();
return _computer;
}
}
当然,还需要我们来进行协调指挥。
public class BOSS
{
/// <summary>
/// 小明组装1台
/// </summary>
/// <returns></returns>
public IComputerDiy GetXiaoMingProduct()
{
return new ComputerBuilderXiaoMing().Product();
}
/// <summary>
/// 王五组装1台
/// </summary>
/// <returns></returns>
public IComputerDiy GetWangWuProduct()
{
return new ComputerBuilderWangWu().Product();
}
/// <summary>
/// 小明组装30台
/// </summary>
/// <returns></returns>
public List<IComputerDiy> GetXiaoMingProducts()
{
List<IComputerDiy> products = new List<IComputerDiy>();
for (int i = 0; i < 30; i++)
{
products.Add(new ComputerBuilderXiaoMing().Product());
}
return products;
}
/// <summary>
/// 王五组装35台
/// </summary>
/// <returns></returns>
public List<IComputerDiy> GetWangWuProducts()
{
List<IComputerDiy> products = new List<IComputerDiy>();
for (int i = 0; i < 35; i++)
{
products.Add(new ComputerBuilderWangWu().Product());
}
return products;
}
}
这样,我们的小作坊就开工啦,开始为土豪老板装电脑。工作了一天,我们来看看装配结果:
static void Main(string[] args)
{
IComputerDiy result;
BOSS boss = new BOSS();
Console.WriteLine("小明装的电脑:");
result = boss.GetXiaoMingProduct();
result.Run();
Console.WriteLine();
Console.WriteLine("王五装的电脑:");
result = boss.GetWangWuProduct();
result.Run();
Console.WriteLine();
Console.WriteLine($"我是小明,我今天装了{boss.GetXiaoMingProducts().Count}台:");
Console.WriteLine($"我是王五,我今天装了{boss.GetWangWuProducts().Count}台:");
Console.ReadKey(false);
}
运行结果:
分析上面的例子,很容易就能发现,建造者模式分为了三层。最下面是要生产的产品,中间是建造者(Builder),不同的建造者按照不同的规则去完成产品的生产。最上面是指挥者(Director),指挥建造者生产对应的产品。这样的分层结构让代码很清晰,很容易就能理解,也是建造者模式的一大优点。说了这么多,不难理解建造者模式的定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
另外,在建造者模式中,也可以将指挥者去掉。去掉指挥者,我们自己去调用建造者即可。最终是否需要指挥者还需要看应用场景。
再来看一下建造者模式的优缺点和应用场景。
优点:
· 调用人员无需关心建造者内部实现,直接调用对外提供的方法即可。即拥有良好的封装性。
· 易于扩展,建造者不够了,创建一个即可。
· 代码清晰,易于理解。
缺点:
貌似没啥缺点~~
综上所述,当遇到相同的方法要产生不同的结果时,就可以使用建造者模式。但在使用的时候也需要灵活搭配,可能一个需求的实现是多个设计模式共同作用之后产生的美妙结果,一个系统就更别说了。
最后,对比与工厂方法模式,它们是不是有很多相同之处呢?特别是最后的调用方式,可以说是毫无区别。但它们最大的不同之处又在什么地方呢?
文章评论