- A+
概述
面临一个复杂对象的创建工作,通常由各个部分的子对象用一定的算法构成。
子部件(对象)比较多,对象不能当作一个完整的对象或者产品使用(邮件:发件人,收件人、抄送人、主题、邮件内容)
子部件需要按照一定的顺序赋值才有一定的意义,在某个子部件没有赋值之前,另一个子部件就无法赋值。
类图
注:该类图来源网上
需求
用组装电脑来说明,如果公司要采购一批电脑,此时采购员不可能自己去买各个组件并把它们组织起来,此时采购员只需要像电脑城的老板说自己要采购什么样的电脑就可以了,电脑城老板自然会把组装好的电脑送到公司。
未使用建造者模式的代码
/// <summary> /// 产品类 /// </summary> public class Computer { private List<string> _servers = new List<string>(); public void AddPart(string part) { _servers.Add(part); } public void ShowComputer() { foreach (var item in _servers) { Console.WriteLine($"正在安装{item}"); } } }
//C#控制台调用 Computer computer = new Computer(); computer.AddPart("i5的cpu"); computer.AddPart("256G的硬盘"); computer.AddPart("32G的内存"); computer.AddPart("17寸的显示器"); computer.AddPart("win7的操作系统"); computer.ShowComputer();
以上就是组装电脑的代码,如果是个人组装一台,那这么玩某种程度上是可以的;对于公司而言,要采购一批电脑,这么玩效率就太低下了,采购员不可能挨个买零件回来自己组装。反正总的来说,浪费时间和精力,所有内容全部需要客户搞定,而且创建对象和客户端强耦合。
使用建造者模式的代码
public interface IBuilderComputer { //1 封装创建各个部件的过程 void BuildCpu(); void BuildDisk(); void BuildMemory(); void BuildScreen(); void BuildSystem(); //2、将创建好的复杂对象返回 Computer GetComputer(); }
public class MyDirectory { public void BuildComputer(IBuilderComputer builderComputer) { builderComputer.BuildCpu(); builderComputer.BuildDisk(); builderComputer.BuildMemory(); builderComputer.BuildScreen(); builderComputer.BuildSystem(); } }
/// <summary> /// 具体建造者一 /// </summary> public class GoodComputer : IBuilderComputer { private Computer _computer=new Computer(); public void BuildCpu() { _computer.AddPart("i7的cpu"); } public void BuildDisk() { _computer.AddPart("2T的固态硬盘"); } public void BuildMemory() { _computer.AddPart("32G的内存"); } public void BuildScreen() { _computer.AddPart("32寸的显示屏的内存"); } public void BuildSystem() { _computer.AddPart("win10的操作系统"); } public Computer GetComputer() { return _computer; } }
/// <summary> /// 具体建造者二 /// </summary> public class BadComputer : IBuilderComputer { private Computer _computer = new Computer(); public void BuildCpu() { _computer.AddPart("i3的cpu"); } public void BuildDisk() { _computer.AddPart("126的机械硬盘"); } public void BuildMemory() { _computer.AddPart("2G的内存"); } public void BuildScreen() { _computer.AddPart("14寸的显示屏的内存"); } public void BuildSystem() { _computer.AddPart("win7的操作系统"); } public Computer GetComputer() { return _computer; } }
/// <summary> /// 产品类 /// </summary> public class Computer { private List<string> _servers = new List<string>(); public void AddPart(string part) { _servers.Add(part); } public void ShowComputer() { foreach (var item in _servers) { Console.WriteLine($"正在安装{item}"); } } }
//C#控制台调用 Console.WriteLine("建造者设计模式正式登场"); IBuilderComputer b1=new GoodComputer(); IBuilderComputer b2 = new BadComputer(); MyDirectory directory = new MyDirectory(); directory.BuildComputer(b1); var goodComputer= b1.GetComputer(); goodComputer.ShowComputer(); directory.BuildComputer(b2); var badComputer= b2.GetComputer(); badComputer.ShowComputer();
以上是使用建造者模式实现采购电脑的代码,现在仅仅是采购了2台,如果采购10台,那就很简单了。
建造者模式比较简单,其实像上面的类图已经说得很明确,abstractBuilder(抽象建造者)、ConcreteBuilder(具体建造者)、product(具体产品)、 Director(指挥者),只要掌握好这4个之间的关系,实现起来照猫画虎。
有人问建造者模式与工厂模式有什么区别?
1、建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
2、创建对象的力度不同,建造者创建复杂的对象,由各路复杂的部件组成,工厂模式创建出的对象都一样。
3、关注点不同,工厂模式只需要把对象创建出来就可以,而建造者不仅要创建出这个对象,还要知道这个对象由哪些部件组成。
4、建造者模式根据建造过程中的顺序不一样,最终的对象部件组成也不一样
总结
不知道大家用得建造者模式多不多,有人说他还没用过,其实像我们的.NetCore里面就有大量的建造者模式的使用,可以在梳理dotnetcore源码时多留意体会一下。有何疑问,欢迎交流。