建造者设计模式也是创建型设计模式,我们之前说过创建型设计模式关注对象的创建,当创建比较复杂的对象时我们可能会用到工厂模式,那啥时候用建造者模式呢?答案是创建比复杂还复杂的对象时。
这边我准备基于上一讲抽象工厂使用的例子来讲解,建议先去看抽象工厂,再来看建造者。
以电脑的生产为例,假设我们生产电脑只需要处理器(CPU)、存储器和显示器这三个,所以要生产出一台电脑,就必须要有这三项,然后按照顺序组装,实例化电脑对象的实例,最后我们才能用电脑这个实例来干活。上一篇为了讲解抽象工厂,我们用电脑干活需要创建三个对象的实例:处理器(CPU)、存储器和显示器,用这三个实例干活。而建造者模式的例子中,只需要一个实例:电脑实例,然后用这个实例干活,但是这个实例的创建比较复杂。
建造者模式定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。用上面的例子来解释就是,创建电脑实例的过程与使用电脑实例的地方是分开的,使用的时候不要关心怎么创建,所以我们可以创建不同的电脑,而使用的地方是不影响的。换言之:客户说我就要一台电脑,你怎么来的我不管,所以只要按照规范生产出来的电脑,就可以供他使用
建造者模式有四个重要的角色:
1、产品类:即我们需要用的复杂对象,比如例子中的:电脑类
2、抽象建造者(Builder): 它可以是一个抽象类,也可以是接口。它内部声明了产品各个部件的创建,比如:安装cpu、安装存储、连接显示器这些步骤的抽象,除了这些部分,一般还会有一个获取产品的方法,用于返回创建的产品类。
3、具体建造者(ConcreteBuilder): 实现抽象建造者,里面包含具体的创建过程,并返回一个具体的产品类。可以有多个具体建造者,用于创建不同的产品实例。
4、指挥者(Director): 安排产品类创建的步骤,相当于是一个设计师,它指导产品类的创建。比如:先安装cpu,再安装存储器,最后连上显示器,交付产品。它依赖抽象建造者,在实例化或者在进行创建的时候需要具体建造者的实例,在指挥者内部不包含任何具体的创建过程,他只是指定了一套顺序,然后按照顺序让具体的建造者来进行创建,最终返回一个具体的产品类。客户端只需要和这个指挥者交互,然后选择一个具体的建造者类,通过构造函数或其他方式传递给指挥者,得到产品类。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
下面看具体的代码:
----------------------------------产品类------------------------------------------
///
/// 产品类:一个电脑
///
public class Computer
{
//假设我们认为这个类的创建很复杂。
public string Name { get; set; }
public string CPU { get; set; }
public string HardDisk { get; set; }
public string Monitor { get; set; }
//获取电脑的配置清单
public void GetConfigurationList()
{
System.Console.WriteLine("--------本机配置清单-----");
System.Console.WriteLine($"--计算机名称:{this.Name}");
System.Console.WriteLine($"--处理器型号:{this.CPU}");
System.Console.WriteLine($"--存储器型号:{this.HardDisk}");
System.Console.WriteLine($"--显示器型号:{this.Monitor}");
}
}
----------------------------------抽象建造者------------------------------------------
///
/// 抽象建造者:包含了一些了步骤的抽象
///
public abstract class ComputerBuilder
{
public abstract void Named();//起名
public abstract void BilderCPU();//安装cpu
public abstract void BilderHardDisk();//安装存储
public abstract void BilderMonitor(); //安装显示器
public abstract Computer GetComputer();//成品出货
}
----------------------------------具体建造者------------------------------------------
--具体建造者1:戴尔电脑
///
/// 具体建造者:戴尔电脑建造者,继承了抽象建造者,并重写了它的方法,有自己具体的独特的建造细节,返回戴尔电脑产品实例
///
public class DellComputerBuilder : ComputerBuilder
{
Computer computer = new Computer();
public override void Named()
{
computer.Name = " dell 高端电脑 ";
}
public override void BilderCPU()
{
computer.CPU = "Inter i9-9900K";
}
public override void BilderHardDisk()
{
computer.HardDisk = "Samsung960EVO";
}
public override void BilderMonitor()
{
computer.Monitor = "Dell2418t";
}
public override Computer GetComputer()
{
return computer;
}
}
--具体建造者2:苹果电脑
///
/// 具体建造者:苹果电脑建造者,继承了抽象建造者,并重写了它的方法,有自己具体的独特的建造细节,返回苹果电脑产品实例
///
public class AppleComputerBuilder : ComputerBuilder
{
Computer computer = new Computer();
public override void Named()
{
computer.Name = " MacBookPro ";
}
public override void BilderCPU()
{
computer.CPU = "Inter i7 八核心Cpu";
}
public override void BilderHardDisk()
{
computer.HardDisk = "专利存储方案,就是快!";
}
public override void BilderMonitor()
{
computer.Monitor = "高清视网膜屏幕,养眼!";
}
public override Computer GetComputer()
{
return computer;
}
}
-------------------------------------指挥者---------------------------------------------
///
/// 指挥者:定义了产品创建的步骤,但是自己不动手,指挥具体建造者来干活
///
public class ComputerDirector
{
private readonly ComputerBuilder _builder;
//构造函数接收一个抽象建造者,所有实现了抽象建造者的具体建造者实例都可以接收,实现不同的建造细节
public ComputerDirector(ComputerBuilder builder)
{
_builder = builder;
}
public Computer GetComputer()
{
_builder.Named(); //1、先起名
_builder.BilderCPU(); //2、安装CPU
_builder.BilderHardDisk(); //3、安装存储
_builder.BilderMonitor(); //4、连接显示器
return _builder.GetComputer(); //返回具体的产品
}
}
----------------------------------客户端代码------------------------------------------
//1、实例化具体建造者
//ComputerBuilder builder = new DellComputerBuilder();
ComputerBuilder builder = new AppleComputerBuilder();
//2、用具体建造者实例,实例化指挥者
ComputerDirector director = new ComputerDirector(builder);
//3、指挥者负责调度具体建造者来创建产品类
var dellComputer = director.GetComputer();
//4、用创建好的产品类,干活
dellComputer.GetConfigurationList();
不同的具体建造者创建除了不同的产品实例,他们都可以查看配置清单,但是结果却不一样: