首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >设计模式讲解01-建造者模式(Builder)

设计模式讲解01-建造者模式(Builder)

作者头像
CodeSuc
发布于 2025-11-03 17:36:13
发布于 2025-11-03 17:36:13
4420
举报

1. 概述

建造者模式也称为:生成器模式

定义:建造者模式是一种创建型设计模式,它允许你将创建复杂对象的步骤与表示方式相分离。

解释:建造者模式就是将复杂对象的创建过程拆分成多个简单对象的创建过程,并将这些简单对象组合成复杂对象!

2. 优缺点

优点

缺点

灵活:可以分步骤地构建复杂对象,使得构建过程更加灵活。

增加工作量:需要额外的代码来创建和管理具体建造者类,增加工作量。

解耦:可以隔离复杂对象的创建和使用,客户端不必关心对象的创建细节。

效率低:相比于其他创建型模式,在运行时效率较低,特别是对象过于复杂时。

易扩展:增加新的具体建造者很方便,可以扩展构建器功能,符合开闭原则。

  1. 灵活:可以分步骤地构建复杂对象,使得构建过程更加灵活。
  2. 增加工作量:需要额外的代码来创建和管理具体建造者类,增加工作量。
  3. 解耦:可以隔离复杂对象的创建和使用,客户端不必关心对象的创建细节。
  4. 效率低:相比于其他创建型模式,在运行时效率较低,特别是对象过于复杂时。
  5. 易扩展:增加新的具体建造者很方便,可以扩展构建器功能,符合开闭原则。

3. 结构

建造者模式包含以下几个主要角色:

  • 产品(Product):要构建的复杂对象;产品类通常包含多个部分或者属性,并由具体的建造者逐步构建而成。
  • 抽象建造者(Builder):定义了构建产品的抽象接口,包括构建产品的各个部分的方法;通常包括多个构建方法和一个返回产品的方法。
  • 具体建造者(Concrete Builder):实现了抽象建造者接口,具体确定如何构建产品的各个部分,并负责返回最终构建的产品。
  • 指导者(Director):负责调用建造者的方法来构建产品;指导者并不了解具体的构建过程,只关心产品的构建顺序和方式。

4. 代码实现

4.1. 需求介绍

我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。

我们将创建一个表示食物条目(比如汉堡和冷饮)的 Item 接口和实现 Item 接口的实体类,以及一个表示食物包装的 Packing 接口和实现 Packing 接口的实体类,汉堡是包在纸盒中,冷饮是装在瓶子中。

然后我们创建一个 Meal 类,带有 Item 的 ArrayList 和一个通过结合 Item 来创建不同类型的 Meal 对象的 MealBuilder。BuilderPatternDemo 类使用 MealBuilder 来创建一个 Meal。

4.2. 代码演示
  1. 创建一个代表食物条目和食物包装的接口。
代码语言:javascript
复制
/**
 * @Description 食品条目接口
 * @Author gongming.Zhang
 * @Date 2024/11/1 15:54
 * @Version 1.0
 */
public interface Item {
    // 商品名称
    String name();
    // 包装类型 (纸盒、瓶子)
    Packing packing();
    // 价格
    float price();
}
代码语言:javascript
复制
package top.zhang.builderdesignpatterns.entity.packing;

/**
 * @Description 食物包装条目接口
 * @Author gongming.Zhang
 * @Date 2024/11/1 15:56
 * @Version 1.0
 */
public interface Packing {
    // 包装类型(纸盒、瓶子)
    String pack();
}
  1. 创建并实现 Packing 接口的实体类。
代码语言:javascript
复制
/**
 * @Description 纸盒实现类
 * @Author gongming.Zhang
 * @Date 2024/11/1 15:57
 * @Version 1.0
 */
public class Wrapper implements Packing {
    @Override
    public String pack() {
        return "Wrapper";
    }
}
代码语言:javascript
复制
/**
 * @Description 瓶子实现类
 * @Author gongming.Zhang
 * @Date 2024/11/1 15:58
 * @Version 1.0
 */
public class Bottle implements Packing {
    @Override
    public String pack() {
        return "Bottle";
    }
}
  1. 创建并实现 Item接口的抽象类,该类提供默认的功能。
代码语言:javascript
复制
/**
 * @Description 汉堡抽象类
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:00
 * @Version 1.0
 */
public abstract class Burger implements Item {

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

    @Override
    public abstract float price();
}
代码语言:javascript
复制
/**
 * @Description 冷饮抽象类
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:24
 * @Version 1.0
 */
public abstract class ColdDrink implements Item {
    @Override
    public Packing packing() {
        return new Bottle();
    }

    @Override
    public abstract float price();
}
  1. 创建并继承 Burger 和 ColdDrink。
代码语言:javascript
复制
/**
 * @Description 鸡肉汉堡实体类
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:28
 * @Version 1.0
 */
public class ChickenBurger extends Burger {
    @Override
    public String name() {
        return "Chicken Burger";
    }

    @Override
    public float price() {
        return 50.5f;
    }
}
代码语言:javascript
复制
/**
 * @Description 素食汉堡实体类
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:26
 * @Version 1.0
 */
public class VegBurger extends Burger {
    @Override
    public String name() {
        return "Veg Burger";
    }

    @Override
    public float price() {
        return 25.0f;
    }
}
代码语言:javascript
复制
/**
 * @Description 可口可乐实体类
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:28
 * @Version 1.0
 */
public class Coke extends ColdDrink {
    @Override
    public String name() {
        return "Coke";
    }

    @Override
    public float price() {
        return 30.0f;
    }
}
代码语言:javascript
复制
/**
 * @Description 百事可乐实体类
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:30
 * @Version 1.0
 */
public class Pepsi extends ColdDrink {
    @Override
    public String name() {
        return "Pepsi";
    }

    @Override
    public float price() {
        return 35.0f;
    }
}
  1. 创建一个 Meal 类,表示菜品实体。(产品)
代码语言:javascript
复制
package top.zhang.builderdesignpatterns.entity;

import top.zhang.builderdesignpatterns.entity.food.Item;

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

/**
 * @Description 菜品实体类  ——  产品
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:31
 * @Version 1.0
 */
public class Meal {
    private List<Item> items = new ArrayList<Item>();

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

    /**
     * 获取购买的商品总价
     *
     * @return 商品总价格
     */
    public float getCost() {
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }
        return cost;
    }

    /**
     * 展示购买的商品信息
     *
     */
    public void showItems() {
        for (Item item : items) {
            System.out.print("Item : "+item.name());
            System.out.print(", Packing : "+item.packing().pack());
            System.out.println(", Price : "+item.price());
        }
    }
}
  1. 创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象。(具体建造者)
代码语言:javascript
复制
package top.zhang.builderdesignpatterns.entity;

import top.zhang.builderdesignpatterns.entity.food.entity.ChickenBurger;
import top.zhang.builderdesignpatterns.entity.food.entity.Coke;
import top.zhang.builderdesignpatterns.entity.food.entity.Pepsi;
import top.zhang.builderdesignpatterns.entity.food.entity.VegBurger;

/**
 * @Description 负责构建 Meal 对象  ——  具体建造者
 * @Author gongming.Zhang
 * @Date 2024/11/1 16:34
 * @Version 1.0
 */
public class MealBuilder {

    /**
     * 构建蔬菜餐数据
     *
     * @return 菜品实体类
     */
    public Meal prepareVegMeal() {
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }

    /**
     * 构建非蔬菜餐数据
     *
     * @return 菜品实体类
     */
    public Meal prepareNonVegMeal() {
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}
  1. 测试建造者模式
代码语言:javascript
复制
@SpringBootTest
@RunWith(SpringRunner.class)
class BuilderDesignPatternsApplicationTests {

    @Test
    public void BuilderPatternDemo() {
        MealBuilder mealBuilder = new MealBuilder();

        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("Veg Meal");
        vegMeal.showItems();
        System.out.println("total Cost: " + vegMeal.getCost());

        System.out.println("\n\n");

        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("Non-Veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost: " +nonVegMeal.getCost());
    }
}

5. 总结

使用场景:

  • 当需要创建一些特定的对象,但是它们拥有共同的组成部分时,比如:一个房子可以由个个部件:框架、墙、窗户等,这些部件可以组合起来构造完整的房子。
  • 当对象的构建过程比较复杂且需要多个步骤时,例如,创建一份电子商务订单需要多个步骤,如选择商品、填写地址和支付等,这些步骤可以被分别封装成为订单构建器中的不同方法。
  • 当需要创建一些特定类型的对象,例如复杂的数据结构或配置对象时,这在编写配置文件解析器以及通用数据结构如二叉树等时很有用。
  • 建造者模式也可以被用于通过更高级的方式来构建复杂对象,例如:序列化和反序列化。

与抽象工厂模式的区别:

抽象工厂模式强调的是产品族的创建,即相关的产品一起被创建出来,而建造者模式强调的是一个复杂对象的创建,即它的各个部分逐步被创建出来。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 1. 概述
  • 2. 优缺点
  • 3. 结构
  • 4. 代码实现
    • 4.1. 需求介绍
    • 4.2. 代码演示
  • 5. 总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档