1.模式简介

      建造者模式(Builder Pattern)属于创建型模式中的一种,在创建比较复杂的对象,或者对象包含多个组成部分时比较有用,用于将对象的创建过程与使用分离,隔离具体的创建细节,方便以后的扩展。它的使用场景包括:

  • 对象的创建比较复杂,需要进行许多处理工作
  • 对象包含多个组成部分,而这几个部分之间常常会有较为固定的顺序
  • 创建对象需要许多参数,会导致构建时的参数列表过长,难以理解和维护

      本文将以一个具体的例子作为引子,通过对比的形式讲解建造者模式的优点,最后引入定义和类图。

2.案例分析

      这里以做菜为例子,通常做菜的步骤包括:放油,放葱姜蒜,加肉,翻炒,加盐,继续翻炒,装盘,那么做一份豆角炒肉代码可以这样写:

复制代码
public class SimpleCook {   public static void main(String[] args) {     SimpleCook cook = new SimpleCook();     cook.cookmeatWithBeans();   }    public void cookmeatWithBeans(){     System.out.println("热锅下油。。。");     System.out.println("加肉。。。");     System.out.println("加入葱姜蒜。。。");     System.out.println("放入豆角。。。");     System.out.println("翻炒均匀。。。");     System.out.println("加盐,继续翻炒。。。");     System.out.println("出锅。。。");   } }
复制代码

      OK,一盘香喷喷的豆角炒肉就做好了。不过,上面的代码还有一些问题:①代码将每个步骤一笔带过,实际上每一步都会有许多细节,比如第一步下油,什么时候倒油,倒多少合适?如果把这些详细步骤全部写在一起,各个步骤之间不仅耦合严重,而且代码还会显得杂乱,一旦某个步骤需要改善,整个方法都受影响;②扩展性问题,如果我想换个藕丁炒肉,那就需要新添加一个方法,没有扩展性。而且我们会发现豆角炒肉和藕丁炒肉所有的步骤都一样,只是把“放入豆角”改成了“放入藕丁”,随着类型菜品的增多,系统会充斥大量的冗余代码。

      因此,这里需要将每个步骤单独提出来作为一个方法,炒菜的步骤修改之后如下:

复制代码
public class SimpleCook {   public static void main(String[] args) {     SimpleCook cook = new SimpleCook();     cook.cookMeatWithBeansBetterWay();   }    public void cookMeatWithBeansBetterWay(){     addOil();     addMeat();     addIngredients();     addDish();     cookForAWhile();     addSalt();     finish();   }    private void finish() {     System.out.println("出锅。。。");   }    private void addSalt() {     System.out.println("加盐,继续翻炒。。。");   }    private void cookForAWhile() {     System.out.println("翻炒均匀。。。");   }    private void addDish() {     System.out.println("放入豆角。。。");   }    private void addIngredients() {     System.out.println("加入葱姜蒜。。。");   }    private void addMeat() {     System.out.println("加肉。。。");   }    private void addOil() {     System.out.println("热锅下油。。。");   } }
复制代码

      由于很多菜品都遵循类似的步骤,只是具体实现不一样,那么就可以抽象出一个父类,然后具体的步骤交给子类去实现,对于其中共同的部分,可以在抽象父类中提供默认实现:

复制代码
public abstract class Builder {   public abstract void addOil();   public abstract