类之间关系

UML类图

图片说明

流程解析

打包packing 有纸盒和瓶装两种。
菜单Item分两类,汉堡和冷饮。
汉堡分鸡肉和蔬菜。冷饮分牛奶和可乐。

现在我们要点餐,需要返回一个菜单的价格和餐品名字的详情。可以看到MealBuider类是最关键的。由于我们点的是一个菜单,需要多个产品。建造者会直接帮我们把菜单解决好,而不是我们自己去添加。

代码部分

两个核心接口

public interface Item {
    public String name();
    public Packing packing();
    public int price();
}

public interface Packing {
    public String pack();
}

接口Packing的实现

public class Wrapper implements Packing {
    @Override
    public String pack() {
        return "用盒子打包";
    }
}

public class Bottle implements Packing {
    @Override
    public String pack() {
        return "用瓶子装给我";
    }
}

接口Item的实现

两个抽象类

可以看到,Item的抽象类和Packing类有一个依赖关系。可以新建Packing接口的实现类

public abstract class Burger implements Item {

    @Override
    public Packing packing() {
        return new Wrapper();
    }

    @Override
    public abstract int price();
}

public abstract class ColdDrink implements Item {

    @Override
    public Packing packing() {
        return new Bottle();
    }

    @Override
    public abstract int price();
}

4个具体实现类

public class Coke extends ColdDrink {

    @Override
    public int price() {
        return 30;
    }

    @Override
    public String name() {
        return "可乐";
    }
}

public class milk extends ColdDrink {

    @Override
    public int price() {
        return 35;
    }

    @Override
    public String name() {
        return "牛奶";
    }
}

public class VegBurger extends Burger {

    @Override
    public int price() {
        return 25;
    }

    @Override
    public String name() {
        return "蔬菜憨包包";
    }
}

public class ChickenBurger extends Burger {

    @Override
    public int price() {
        return 50;
    }

    @Override
    public String name() {
        return "鸡肉憨包包";
    }
}

Meal类

这个类完成了价格的计算,以及最后的菜单打印功能。

import java.util.ArrayList;
import java.util.List;

public class Meal {
    private List<Item> items = new ArrayList<Item>();

    public void addItem(Item item){
        items.add(item);
    }

    public int getCost(){
        int cost = 0;
        for (int i=0;i<items.size();i++) {
            cost += items.get(i).price();
        }
        return cost;
    }

    public void showItems(){
        for (int i=0;i<items.size();i++) {
            System.out.print("Item : "+items.get(i).name());
            System.out.print(", Packing : "+items.get(i).packing().pack());
            System.out.println(", Price : "+items.get(i).price());
        }
    }
}

MealBuilder 类

这个类完成了Meal类的建造,点餐的功能,即将菜品加入到meal对象中。

public class MealBuilder {

    public Meal prepareVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }

    public Meal prepareNonVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new milk());
        return meal;
    }
}

Demo测试类

我们只需要知道,有一个点餐系统即MealBuilder,因此我们需要new一个这个类的对象,并且我们知道最终我们点的是一个菜单,因此Meal对象也是我们所知道的,但是不需要我们new,让MealBuider帮我们完成,正常来说,我们告诉他点一个蔬菜套餐,就能告诉我们详情,这里没有使用反射,因此是直接调用的mealBuilder.prepareVegMeal(),正常来说,我们告诉他要点一个蔬菜套餐,然后通过反射,然后取建立蔬菜菜单。

public class DemoMain {
    public static void main(String[] args) {
        MealBuilder mealBuilder = new MealBuilder();

        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("素材套餐");
        vegMeal.showItems();
        System.out.println("总价格: " +vegMeal.getCost());

        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("荤菜套餐");
        nonVegMeal.showItems();
        System.out.println("总价格: " +nonVegMeal.getCost());
    }
}

运行结果

素材套餐
Item : 蔬菜憨包包, Packing : 用盒子打包, Price : 25
Item : 可乐, Packing : 用瓶子装给我, Price : 30
总价格: 55
荤菜套餐
Item : 鸡肉憨包包, Packing : 用盒子打包, Price : 50
Item : 牛奶, Packing : 用瓶子装给我, Price : 35
总价格: 85

总结:

可以很明显的看到,一个组装的过程,我们点一个蔬菜套餐,就要将蔬菜汉堡和可乐都加入到菜单中。建造者之所以称为建造者,就是因为建造是一个过程,因此这个模式更多的是关心这个最终的产品,是如何一步步形成的,而不是像我们之前学习的抽象工厂模式那样,直接返回一个产品。