Builder模式

Builder模式

Posted by Anriku on March 30, 2018

Builder模式简单介绍

Builder模式是一种将对象的构造和对象的使用分开的设计模式。而且可以利用不同的构造方案以及不同的构造过程来实现构造不同对象。

本次示例代码的UML图

Builder Pattern

我们来分析一下上面的UML图,其实这个实现东西很简单。就是一个我们去堕落街吃干锅的一副场景。故事都是要有主角分析的,我们来分析一下主角吧:

  • Cook:咱们的大厨
  • FoodBuilder:厨师通过菜谱做菜的过程
  • GanGuoBuilder:根据菜谱做干锅的过程
  • Food:一个食物接口
  • GanGuo:重点来了,我们吃的就是这东西
  • …(黄焖鸡我们就不分析了,是一样的)

具体的代码分析

现在我们把全部的代码拿上来再进行具体的分析:

public class Cook {

    private FoodBuilder foodBuilder;

    public void setFoodBuilder(FoodBuilder foodBuilder) {
        this.foodBuilder = foodBuilder;
    }

    public Food cook(){
        if (foodBuilder != null){
            return foodBuilder.getFood();
        }
        return null;
    }
}




public abstract class FoodBuilder {

    abstract FoodBuilder setSpicyDegree(boolean isSpicy);

    abstract FoodBuilder setAmount(int amount);

    abstract FoodBuilder setAddition(String addition);

    abstract Food getFood();

}


public interface Food {
}


public class GanGuo implements Food {

    private boolean isSpicy = false;
    private int amount = 10;
    private String addition = "liji and paigu";

    public void beEaten(){
        System.out.println("被吃掉了");
    }

    static class GanGuoBuilder extends FoodBuilder {

        private GanGuo ganGuo = new GanGuo();

        @Override
        FoodBuilder setSpicyDegree(boolean isSpicy) {
            ganGuo.isSpicy = isSpicy;
            return this;
        }

        @Override
        FoodBuilder setAmount(int amount) {
            ganGuo.amount = amount;
            return this;
        }

        @Override
        FoodBuilder setAddition(String addition) {
            ganGuo.addition = addition;
            return this;
        }

        @Override
        Food getFood() {
            return ganGuo;
        }
    }
}

public class CleverYou{
    public static void main(String[] args) {

        Cook cook = new Cook();

        FoodBuilder ganGuoBuilder = new GanGuo.GanGuoBuilder().setSpicyDegree(false)
                .setAmount(15);
        cook.setFoodBuilder(ganGuoBuilder);
        GanGuo ganGuo = (GanGuo) cook.cook();
        ganGuo.beEaten();

        FoodBuilder huangMenJiBuilder = new HuangMenJi.HuangMenJiBuilder().setSpicyDegree(true)
                .setAmount(20).setAddition("土豆鸡");
        cook.setFoodBuilder(huangMenJiBuilder);
        HuangMenJi huangMenJi = (HuangMenJi) cook.cook();
        huangMenJi.beEaten();

    }
}

上面的代码我们一步一步的来进行一下分析。

  • 首先是Cook的对象通过setFoodBuilder方法来进行具体食物制作的传入。后面Cook的对象通过cook方法来得到构建的具体Food对象。
  • 然后FoodBuilder是一个抽象类,Food是一个接口都是用于面向抽象的编程(面向接口编程)的。
  • 我们看到GanGuo类,其中GanGuo类中有一个GanGuoBuilder的静态内部类,这个类就是用来对GanGuo类进行构建的。这里我们利用了静态内部类中的外部类对象可以直接访问外部类的特点,来进行GanGuo对象的创建的,这样的话外部类需要构建的类的静态成员变量就不用设置setter方法来进行对象的构造了。因此,我们对象的构造就和对象的使用进行了分离,也就是我们外部需要构建的类就只需要写我们的使用方法了。
  • 最后,CleverYou就是调用者,我们可以很明显的看到,干锅和黄焖鸡都通过自己的FoodBuilder进行了构造。通过将Builder传给了Cook进行食物的构建。

其实很多的时候,像Cook这样的角色是不需要的。我们要构建一个对象直接通过Builder进行创建就行的。这里我们也可以完全把Cook给去掉的,其实Cook的cook方法就是调用FoodBuilder中的getFood方法获得已经构造好的方法。我们这里之所以加上,是让一切更加地符合常理。

Builder模式的好处

可以实现链式调用:我们进行链式对象组装其实很简单就是通过每个构建对象方法后面都返回这个对象本身。

可以将对象的构建和对象的使用分开: 我们知道为了一个类的安全,我们常常将一个类的成员属性设置private。如果我们想在外部进行对象的成员属性的改变的话,我们必须给这些属性设置setter方法,然后这会照成什么问题呢?如果成员属性过多的话,我们这个类中会有很多setter方法,让这个类很臃肿。这个时候,我们可以静态内部类中的外部类对象可以直接访问其中的private属性的特点来进行解决。

可以实现不同的构造:如果我们通过构造器来实现不同的构造,也就是这个构造器中通过不同成员属性的设置来进行构造的时候,我们必须要设置很多的不同的构造器。而我们通Builder模式的实现可以直接通过Builder设置属性的set方法的个数或者是顺序来进行不同对象的构造(本例可以体现前面)。

总结

  • Builder模式的话,主要是在我们进行复杂对象的构造的时候将对象的构造和对象的使用进行分开的。设计模式这东西没有什么完全固定的格式,这个根据我们具体的情况会做一些具体的修改,理解其中的原理就好。

参考

  • 《Android源码设计模式》