设计模式--创建型模式--建造者模式
建造者模式
什么是建造者模式?
文档资料中的解释
建造者模式:用多个简单的对象,一步一步构建成一个复杂的对象;构建的过程,由另一个更专业的Builder处理。
建造者模式的本质是什么?
将不变的基础组件 与 经常变化的组件组合 分离开,提高代码的可扩展性。
类似于:饭店里的各种各样的套餐,每一个套餐是不一样的,但里面的单品有可能是相同的。
实现案例代码
/**
* 创建型模式:
* 建造者模式测试
*
* 适用场景为:
* 基础部件不变,但部件之间的组合经常变化
*
* 案例:
* 肯德基的套餐:
* 套餐1:汉堡+可乐
* 套餐2:汉堡+鸡腿
* 套餐3:汉堡+鸡米花
* 套餐4:汉堡+可乐+鸡腿
* 基础部件为:
* 汉堡、鸡腿、鸡米花、 可乐、牛奶
*/
public class BuilderTest {
public static void main(String[] args) {
// TODO
MealBuilder mbl = new MealBuilder();
mbl.taoCan1();
}
}
/* ===================== 接口 ========================== */
interface Food {
/**
* 食物的名称
* @return
*/
String name();
/**
* 食物的价格
* @return
*/
BigDecimal price();
}
/**
* 主食
*/
interface ZhuShi extends Food {
}
/**
* 冷饮
*/
interface Drink extends Food {
}
/**
* 套餐
*/
class Meal {
private List<Food> foods = new ArrayList<>(6);
/**
* 套餐里面添加:食物
* @param food
*/
public void add(Food food) {
this.foods.add(food);
}
/**
* 获取套餐的价格
* @return
*/
public BigDecimal getCost() {
BigDecimal total = new BigDecimal("0.0");
for(Food food : foods) {
total = total.add(food.price());
}
return total;
}
/**
* 打印套餐的内容和总价格
*/
public void showTotalCost() {
System.out.print("套餐内含有: ");
for(int index=0; index<foods.size(); index++) {
Food food = foods.get(index);
System.out.print(food.name());
if (index != foods.size()-1) {
System.out.print(" ");
}
}
System.out.print(", 总价格为: "+getCost()+"元");
System.out.println("");
}
/**
* 打印每个食品的名称、价格
*/
public void showFoods() {
for(Food food : foods) {
System.out.println("\t食物: "+food.name()+", 价格: "+food.price());
}
}
}
class MealBuilder {
/**
* 所有的套餐列表
*/
private List<Meal> meals = new ArrayList<>();
/**
* 套餐一
* @return
*/
public List<Meal> taoCan1() {
Meal meal = new Meal();
meal.add(new Hanbao());
meal.add(new JiMiHua());
meal.add(new Milk());
meal.showTotalCost();
meal.showFoods();
this.meals.add(meal);
return this.meals;
}
/**
* 1~2个主食,1杯饮料
* @return
*/
// public List<Meal> generateMeals() {
// for() {
// Meal meal = randomMeal();
// if (!this.meals.contains(meal)) {
// this.meals.add(meal);
// }
// }
// }
private Meal randomMeal() {
Meal meal = new Meal();
final int zhuShiCount = 2;
final int drinkCount = 1;
for (int i=0; i<zhuShiCount; i++) {
meal.add(randomZhuShi());
}
for (int i=0; i<drinkCount; i++) {
meal.add(randomDrink());
}
return meal;
}
/**
* 随机饮料
* @return
*/
private Food randomDrink() {
Class<Food>[] clazz = new Class[]{Milk.class, Coca.class};
Random random = new Random(clazz.length);
final int i = random.nextInt();
final Class<Food> foodClass = clazz[i];
try {
return foodClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* 随机主食
* @return
*/
private Food randomZhuShi() {
Class<Food>[] clazz = new Class[]{Hanbao.class, JiTui.class, JiMiHua.class};
Random random = new Random(clazz.length);
final int i = random.nextInt();
final Class<Food> foodClass = clazz[i];
try {
return foodClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
/* ===================== 实现类 ========================== */
/**
* 汉堡-主食
*/
class Hanbao implements ZhuShi {
@Override
public String name() {
return "汉堡";
}
@Override
public BigDecimal price() {
return new BigDecimal("12");
}
}
/**
* 鸡腿-主食
*/
class JiTui implements ZhuShi {
@Override
public String name() {
return "鸡腿";
}
@Override
public BigDecimal price() {
return new BigDecimal("8.5");
}
}
/**
* 鸡米花-主食
*/
class JiMiHua implements ZhuShi {
@Override
public String name() {
return "鸡米花";
}
@Override
public BigDecimal price() {
return new BigDecimal("8.0");
}
}
/**
* 牛奶-饮料
*/
class Milk implements Drink {
@Override
public String name() {
return "牛奶";
}
@Override
public BigDecimal price() {
return new BigDecimal("4.0");
}
}
/**
* 可乐-饮料
*/
class Coca implements Drink {
@Override
public String name() {
return "可乐";
}
@Override
public BigDecimal price() {
return new BigDecimal("3.0");
}
}
稍微复杂点的场景
假设现在有在现有的菜式上,推出了新的套餐:套餐二、套餐三、套餐四,应该如何设计???
将
MealBuilder定义成一个接口,所有的套餐构建都实现这个接口 即可。代码如下:
package test2;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* 创建型模式:
* 建造者模式测试
*
* 适用场景为:
* 基础部件不变,但部件之间的组合经常变化
*
* 案例:
* 肯德基的套餐:
* 套餐1:汉堡+可乐
* 套餐2:汉堡+鸡腿
* 套餐3:汉堡+鸡米花
* 套餐4:汉堡+可乐+鸡腿
* 基础部件为:
* 汉堡、鸡腿、鸡米花、 可乐、牛奶
*/
public class BuilderTest2 {
public static void main(String[] args) {
MealBuilder mbl = new TaoCan1MealBuilder();
Meal meal = mbl.packMeal();
meal.showTotalCost();
meal.showFoods();
System.out.println("================================================");
MealBuilder mbl2 = new TaoCan2MealBuilder();
Meal meal2 = mbl2.packMeal();
meal2.showTotalCost();
meal2.showFoods();
System.out.println("================================================");
MealBuilder mbl3 = new TaoCan3MealBuilder();
Meal meal3 = mbl3.packMeal();
meal3.showTotalCost();
meal3.showFoods();
}
}
/* ===================== 接口 ========================== */
interface Food {
/**
* 食物的名称
* @return
*/
String name();
/**
* 食物的价格
* @return
*/
BigDecimal price();
}
/**
* 主食
*/
interface ZhuShi extends Food {
}
/**
* 冷饮
*/
interface Drink extends Food {
}
/**
* 套餐
*/
class Meal {
private List<Food> foods = new ArrayList<>(6);
/**
* 套餐里面添加:食物
* @param food
*/
public void add(Food food) {
this.foods.add(food);
}
/**
* 获取套餐的价格
* @return
*/
public BigDecimal getCost() {
BigDecimal total = new BigDecimal("0.0");
for(Food food : foods) {
total = total.add(food.price());
}
return total;
}
/**
* 打印套餐的内容和总价格
*/
public void showTotalCost() {
System.out.print("套餐内含有: ");
for(int index=0; index<foods.size(); index++) {
Food food = foods.get(index);
System.out.print(food.name());
if (index != foods.size()-1) {
System.out.print(" ");
}
}
System.out.print(", 总价格为: "+getCost()+"元");
System.out.println("");
}
/**
* 打印每个食品的名称、价格
*/
public void showFoods() {
for(Food food : foods) {
System.out.println("\t食物: "+food.name()+", 价格: "+food.price());
}
}
}
/* ========================= 构建者 ========================== */
interface MealBuilder {
Meal packMeal();
}
/**
* 套餐一
*/
class TaoCan1MealBuilder implements MealBuilder {
@Override
public Meal packMeal() {
Meal meal = new Meal();
meal.add(new Hanbao());
meal.add(new JiMiHua());
meal.add(new Milk());
return meal;
}
}
class TaoCan2MealBuilder implements MealBuilder {
@Override
public Meal packMeal() {
Meal meal = new Meal();
meal.add(new Hanbao());
meal.add(new JiTui());
meal.add(new Milk());
return meal;
}
}
class TaoCan3MealBuilder implements MealBuilder {
@Override
public Meal packMeal() {
Meal meal = new Meal();
meal.add(new JiMiHua());
meal.add(new JiTui());
meal.add(new Coca());
return meal;
}
}
//class MealBuilder {
// /**
// * 所有的套餐列表
// */
// private List<Meal> meals = new ArrayList<>();
//
// /**
// * 套餐一
// * @return
// */
// public List<Meal> taoCan1() {
// Meal meal = new Meal();
// meal.add(new Hanbao());
// meal.add(new JiMiHua());
// meal.add(new Milk());
//
// meal.showTotalCost();
// meal.showFoods();
//
// this.meals.add(meal);
// return this.meals;
// }
//
// /**
// * 1~2个主食,1杯饮料
// * @return
// */
//// public List<Meal> generateMeals() {
//// for() {
//// Meal meal = randomMeal();
//// if (!this.meals.contains(meal)) {
//// this.meals.add(meal);
//// }
//// }
//// }
//
// private Meal randomMeal() {
// Meal meal = new Meal();
// final int zhuShiCount = 2;
// final int drinkCount = 1;
//
// for (int i=0; i<zhuShiCount; i++) {
// meal.add(randomZhuShi());
// }
//
// for (int i=0; i<drinkCount; i++) {
// meal.add(randomDrink());
// }
//
// return meal;
// }
//
// /**
// * 随机饮料
// * @return
// */
// private Food randomDrink() {
// Class<Food>[] clazz = new Class[]{Milk.class, Coca.class};
// Random random = new Random(clazz.length);
// final int i = random.nextInt();
// final Class<Food> foodClass = clazz[i];
// try {
// return foodClass.newInstance();
// } catch (InstantiationException e) {
// e.printStackTrace();
// } catch (IllegalAccessException e) {
// e.printStackTrace();
// }
// return null;
// }
//
// /**
// * 随机主食
// * @return
// */
// private Food randomZhuShi() {
// Class<Food>[] clazz = new Class[]{Hanbao.class, JiTui.class, JiMiHua.class};
// Random random = new Random(clazz.length);
// final int i = random.nextInt();
// final Class<Food> foodClass = clazz[i];
// try {
// return foodClass.newInstance();
// } catch (InstantiationException e) {
// e.printStackTrace();
// } catch (IllegalAccessException e) {
// e.printStackTrace();
// }
// return null;
// }
//
//}
/* ===================== 实现类 ========================== */
/**
* 汉堡-主食
*/
class Hanbao implements ZhuShi {
@Override
public String name() {
return "汉堡";
}
@Override
public BigDecimal price() {
return new BigDecimal("12");
}
}
/**
* 鸡腿-主食
*/
class JiTui implements ZhuShi {
@Override
public String name() {
return "鸡腿";
}
@Override
public BigDecimal price() {
return new BigDecimal("8.5");
}
}
/**
* 鸡米花-主食
*/
class JiMiHua implements ZhuShi {
@Override
public String name() {
return "鸡米花";
}
@Override
public BigDecimal price() {
return new BigDecimal("8.0");
}
}
/**
* 牛奶-饮料
*/
class Milk implements Drink {
@Override
public String name() {
return "牛奶";
}
@Override
public BigDecimal price() {
return new BigDecimal("4.0");
}
}
/**
* 可乐-饮料
*/
class Coca implements Drink {
@Override
public String name() {
return "可乐";
}
@Override
public BigDecimal price() {
return new BigDecimal("3.0");
}
}
JDK、Spring中建造者的应用
JDK
String类的构建:StringBuilder
Spring
BeanDefinition的构建BeanDefinitionBuilder
本文来自博客园,作者:小小落,转载请注明原文链接:https://www.cnblogs.com/dyorick/p/15534035.html

浙公网安备 33010602011771号