思路:
当我们需要一辆车,却发现只有这辆车的所有零件(我们简化为车轮、油箱和车身三个部件),需要我们把它组装起来,我们该怎么做呢?
class Program { static void Main(string[] args) { CarBuilder car = new CarBuilder(); car.BuildWheel(); car.BuildOilBox(); car.BuildBody(); } } class CarBuilder { public void BuildWheel() { Console.WriteLine("我建造了车轮"); } public void BuildOilBox() { Console.WriteLine("我建造了油箱"); } public void BuildBody() { Console.WriteLine("我建造了车身"); } }
这里有一个隐含的问题,我们现在建造的是含有三个部件的产品,如果一个对象有很多个组成部分,万一我们在设计的时候少写了生产某一个部件的方法,就会导致用户没有这个方法可用,那么就算用户都按照步骤操作,也无法完成这辆车的建造。
那么,我们该用什么方法来预防程序员在写相应方法的时候可能会落下的问题呢?
这里我们可以用到抽象类和抽象方法。即子类继承父类,父类的抽象方法如果不被重写,系统会报错,即可有效的避免这个问题。
class Program { static void Main(string[] args) { CarBuilder car = new CarBuilder(); car.BuildWheel(); car.BuildOilBox(); //car.BuildBody(); Console.ReadKey(); } } abstract class Build { abstract public void BuildWheel(); abstract public void BuildOilBox(); abstract public void BuildBody(); } class CarBuilder:Build { //如果某一个方法不重写,则无法编译通过。 public override void BuildWheel() { Console.WriteLine("我建造了车轮"); } public override void BuildOilBox() { Console.WriteLine("我建造了油箱"); } public override void BuildBody() { Console.WriteLine("我建造了车身"); } }
通过这样的方法,如上的问题便可有效地解决,一旦少写了某一个事先预定好的方法,系统便会提醒你少写了某一个方法。
解决了这样的问题,新的问题又来了。因为我们生产的方法都交给客户在调用,我们所有的方法都提供完备了,但是如果用户忘记了某个办法,这辆车还是建造完成。我们又该怎样让客户不会忘记某一个必要的步骤呢?
其次,当我们把所有方法的调用都暴露给客户,其实会有许多的隐患。事实上用户只关心是否有这个功能,而不关心这个功能是怎么实现的。并且,如果你高高兴兴的去买了一台IPhone,拆开包装盒却发现所有零件都需要自己组装,我想,你会感觉厌烦甚至不高兴的。
在这个代码中同样如此,客户需要的是一辆车,而不是制造车轮、油箱、和车身的方法。
由此,我们可以额外添加一个指挥者类。由这个指挥者指挥建造者创建相关部件,并完成组装。而客户只需要向指挥者要车即可,并不需要关心车是怎么制造和组装的。
并且,满足上述条件的代码设计可以满足用户拥有多辆车的试想。
class Program { static void Main(string[] args) { CarBMWBuilder BMW = new CarBMWBuilder(); CarBuildDirector BMWBuilder = new CarBuildDirector(BMW); BMWBuilder.BuildCar(); CarBenZBuilder BenZ = new CarBenZBuilder(); CarBuildDirector BenZBuilder = new CarBuildDirector(BenZ); BenZBuilder.BuildCar(); Console.ReadKey(); } } class CarBuildDirector { private CarBuilder cb; public CarBuildDirector(CarBuilder cb) { this.cb=cb; } public void BuildCar() { cb.BuildBody(); cb.BuildOilBox(); cb.BuildWheel(); Console.WriteLine("我成功建造了一辆车!"); Console.WriteLine(); } } abstract class CarBuilder { public abstract void BuildWheel(); public abstract void BuildOilBox(); public abstract void BuildBody(); } class CarBMWBuilder : CarBuilder { public override void BuildWheel() { Console.WriteLine("我建造了BMW的车轮"); } public override void BuildOilBox() { Console.WriteLine("我建造了BMW的油箱"); } public override void BuildBody() { Console.WriteLine("我建造了BMW的车身"); } } class CarBenZBuilder : CarBuilder { public override void BuildWheel() { Console.WriteLine("我建造了BenZ的车轮"); } public override void BuildOilBox() { Console.WriteLine("我建造了BenZ的油箱"); } public override void BuildBody() { Console.WriteLine("我建造了BenZ的车身"); } }
UML图:
吐槽:
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。
优点:
1、建造者模式的使用使得产品的内部组成可以独立的变化,使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、每一个Builder都相对独立,而与其他的Builder无关。
3、模式所建造的最终产品更易于控制。
使用情景:
1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到。
本菜鸟的疑难杂症:
学一点记一点真的不容易忘。