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