1、建造者模式的概念
建造者模式,英文Builder Pattern,属于创建型模式,该模式组合多个简单的对象来构造一个复杂的对象。会有一个Builder类,而该类负责构造最终的复杂对象。
2、建造者模式的特点
- 组合多个简单对象,构造复杂对象。
- 由构造类Builder来构造最终的对象。
3、关于建造者模式
- 使用目的:将一个复杂的构建与其表示分离,使得同样的构建能产生不同的组合。
- 解决问题:在开发时,有时候需要创建一个复杂的对象,而这个对象是由多个简单的子对象组合而成的。有时候需要有一点变化,所以希望组合方式不同,但是组合的过程却是一样的。
- 使用时机:基本组件不变,而组合方式经常发生变化。
- 保证建造者:将变化的部分和不变化的部分分离。
- 建造者关键:由一个Builder类来创建提供实例,另一个类负责管理该实例的依赖。
4、建造者模式的优缺点
优点:
- 建造者独立,易扩展。
- 便于控制细节风险。
缺点:
- 产品必须有共同点,范围有限制。
- 如果内部变化复杂,那么需要很多的建造类Builder类。
5、建造者模式的使用场景
- 需要生成的对象具有复杂的内部结构。
- 需要生成的对象内部属性本身相互依赖。
需要注意建造者模式和工厂模式的区别。
6、建造者模式的实现
我们在去KFC吃东西的时候,假如点的套餐是汉堡 + 饮料,那么汉堡可以是牛肉汉堡,也可以是鸡肉汉堡等,店家是使用纸盒来包装汉堡的,饮料可以是可乐,也可以是苹果汁,橙汁等,店家是使用瓶子来装饮料的。所以这里可以创建一个食物条目的Item接口和实现类,然后创建包装Pack的接口和实现类,然后创建一个Food类,该类中带有食物条目Item对象,然后再创建一个FoodBuilder类来产生不同的Food类对象(组合不同的汉堡和饮料)。
(1)创建Pack接口和实现类
/*
* 这个接口表示包装,纸盒还是瓶子
*/
public interface Pack {
// 获取包装名称
public String getPackName();
}
// 纸盒包装
public class PaperBox implements Pack{
@Override
public String getPackName() {
return "使用纸盒包装汉堡!";
}
}
// 瓶子包装
public class Bottle implements Pack{
@Override
public String getPackName() {
return "饮料进行装瓶!";
}
}
(2)创建Item接口和抽象实现类
/*
* 该接口表示食物的条目
*/
public interface Item {
// 获取食物名称
public String getFoodName();
// 获取包装
public Pack packing();
// 获取价格
public float getPrice();
创建Hamburger抽象类,表示汉堡,实现Item接口。
/*
* 汉堡抽象类,实现接口,可以不实现接口中的方法
* 也可以重写接口中的方法
*/
public abstract class Hamburger implements Item{
// 汉堡使用纸盒打包
@Override
public Pack packing() {
return new PaperBox();
}
// 这个方法不实现
@Override
public abstract float getPrice();
}
创建Hamburger抽象类的子类:
// 鸡肉汉堡
public class ChickenHamburger extends Hamburger{
@Override
public String getFoodName() {
return "美味的鸡肉汉堡!";
}
@Override
public float getPrice() {
return 7.5f;
}
}
// 牛肉汉堡
public class BeefHamburger extends Hamburger{
@Override
public String getFoodName() {
return "美味的牛肉汉堡!";
}
@Override
public float getPrice() {
return 8.5f;
}
}
创建Drink抽象类,表示饮料,实现Item接口。
/*
* 饮料抽象类
*/
public abstract class Drink implements Item{
// 饮料使用瓶子进行打包
@Override
public Pack packing() {
return new Bottle();
}
// 这个方法不实现
@Override
public abstract float getPrice();
}
创建Drink抽象类的子类:
/*
* 饮料的子类,可乐
*/
public class Coke extends Drink{
@Override
public String getFoodName() {
return "可口可乐,畅饮无限!";
}
@Override
public float getPrice() {
return 4.5f;
}
}
/*
* 饮料子类,橙汁
*/
public class OrangeJuice extends Drink{
@Override
public String getFoodName() {
return "鲜榨橙汁!";
}
@Override
public float getPrice() {
return 3.0f;
}
}
(3)创建Food类
创建Food类,会带有Item接口。
public class Food {
// 食物条目列表
private List<Item> items = new ArrayList<>();
// 添加食物条目
public void addItems(Item item) {
items.add(item);
}
// 计算总价格
public float getTotalPrice() {
float total = 0.0f;
for (Item item : items) {
total += item.getPrice();
}
return total;
}
// 输出信息
public void showItems() {
for(Item item:items) {
System.out.println("名称:" + item.getFoodName()
+ ",打包:" + item.packing().getPackName()
+ ",价格:" + item.getPrice());
}
}
}
(4)创建FoodBuilder类
创建一个FoodBuilder类,该类负责构建Food类对象,Food类对象是最终要构建的对象,使用了多个简单子对象进行构建。
/*
* 该Builder类只负责构建Food类对象
* 使用多个简单对象进行组合
*/
public class FoodBuilder {
// 鸡肉汉堡 + 可乐套餐
public Food chickenBurgeAndCoke() {
Food food = new Food();
food.addItem(new ChickenHamburger());
food.addItem(new Coke());
return food;
}
// 牛肉汉堡 + 可乐套餐
public Food beefBurgeAndCoke() {
Food food = new Food();
food.addItem(new BeefHamburger());
food.addItem(new Coke());
return food;
}
// 鸡肉汉堡 + 橙汁套餐
public Food chickenBurgeAndOrangeJuice() {
Food food = new Food();
food.addItem(new ChickenHamburger());
food.addItem(new OrangeJuice());
return food;
}
// 牛肉汉堡 + 橙汁套餐
public Food beefBurgeAndOrangeJuice() {
Food food = new Food();
food.addItem(new BeefHamburger());
food.addItem(new OrangeJuice());
return food;
}
}
(5)测试
public class Test {
public static void main(String[] args) {
// FoodBuilder对象
FoodBuilder foodBuilder = new FoodBuilder();
// 套餐一组合
Food chickenCoke = foodBuilder.chickenBurgeAndCoke();
chickenCoke.showItems();
System.out.println("总计:" + chickenCoke.getTotalPrice() + "元");
System.out.println("-----------------------------------------");
// 套餐二组合
Food beefCoke = foodBuilder.beefBurgeAndCoke();
beefCoke.showItems();
System.out.println("总计:" + beefCoke.getTotalPrice() + "元");
System.out.println("-----------------------------------------");
// 套餐三组合
Food chickenJucie = foodBuilder.chickenBurgeAndOrangeJuice();
chickenJucie.showItems();
System.out.println("总计:" + chickenJucie.getTotalPrice() + "元");
System.out.println("-----------------------------------------");
// 套餐四组合
Food beefJucie = foodBuilder.beefBurgeAndOrangeJuice();
beefJucie.showItems();
System.out.println("总计:" + beefJucie.getTotalPrice() + "元");
}
}
7、小结
建造者模式属于创建型模式,其特点是组合多个简单的子对象,来构建一个最终的复杂对象,涉及到一个Builder类来构建最终对象。如果希望有多种组合方式,但是组合过程不变的话,那么使用该模式会是很好的解决方法。