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

ops/2024/11/12 8:54:19/

1. 概述

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

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

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

2. 优缺点

优点

缺点

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

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 类,带有 ItemArrayList 和一个通过结合 Item 来创建不同类型的 Meal 对象的 MealBuilderBuilderPatternDemo 类使用 MealBuilder 来创建一个 Meal

4.2. 代码演示

  1. 创建一个代表食物条目和食物包装的接口。
/*** @Description 食品条目接口* @Author gongming.Zhang* @Date 2024/11/1 15:54* @Version 1.0*/
public interface Item {// 商品名称String name();// 包装类型 (纸盒、瓶子)Packing packing();// 价格float price();
}
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 接口的实体类。
/*** @Description 纸盒实现类* @Author gongming.Zhang* @Date 2024/11/1 15:57* @Version 1.0*/
public class Wrapper implements Packing {@Overridepublic String pack() {return "Wrapper";}
}
/*** @Description 瓶子实现类* @Author gongming.Zhang* @Date 2024/11/1 15:58* @Version 1.0*/
public class Bottle implements Packing {@Overridepublic String pack() {return "Bottle";}
}

  1. 创建并实现 Item接口的抽象类,该类提供默认的功能。
/*** @Description 汉堡抽象类* @Author gongming.Zhang* @Date 2024/11/1 16:00* @Version 1.0*/
public abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}@Overridepublic abstract float price();
}
/*** @Description 冷饮抽象类* @Author gongming.Zhang* @Date 2024/11/1 16:24* @Version 1.0*/
public abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}@Overridepublic abstract float price();
}

  1. 创建并继承 BurgerColdDrink
/*** @Description 鸡肉汉堡实体类* @Author gongming.Zhang* @Date 2024/11/1 16:28* @Version 1.0*/
public class ChickenBurger extends Burger {@Overridepublic String name() {return "Chicken Burger";}@Overridepublic float price() {return 50.5f;}
}
/*** @Description 素食汉堡实体类* @Author gongming.Zhang* @Date 2024/11/1 16:26* @Version 1.0*/
public class VegBurger extends Burger {@Overridepublic String name() {return "Veg Burger";}@Overridepublic float price() {return 25.0f;}
}
/*** @Description 可口可乐实体类* @Author gongming.Zhang* @Date 2024/11/1 16:28* @Version 1.0*/
public class Coke extends ColdDrink {@Overridepublic String name() {return "Coke";}@Overridepublic float price() {return 30.0f;}
}
/*** @Description 百事可乐实体类* @Author gongming.Zhang* @Date 2024/11/1 16:30* @Version 1.0*/
public class Pepsi extends ColdDrink {@Overridepublic String name() {return "Pepsi";}@Overridepublic float price() {return 35.0f;}
}

  1. 创建一个 Meal 类,表示菜品实体。(产品)
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 对象。(具体建造者)
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. 测试建造者模式
@SpringBootTest
@RunWith(SpringRunner.class)
class BuilderDesignPatternsApplicationTests {@Testpublic 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. 总结

使用场景

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

与抽象工厂模式的区别

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


http://www.ppmy.cn/ops/131887.html

相关文章

实践出真知:MVEL表达式中for循环的坑

目录标题 背景MVEL脚本(有问题的)MVEL脚本(正确的)结论分析 背景 需要从一个URL的拼接参数中解析出id的值并输出 比如&#xff1a; 存在URLhttps://xxxxxxxxxx?id999999&type123&name345 然后需要输出id999999 MVEL脚本(有问题的) 入参&#xff1a;parseThisUrlhttp…

数字信号处理Python示例(8)使用复数指数函数生成正弦函数和余弦函数

文章目录 前言一、相量叠加原理二、使用旋转相量生成余弦和正弦波的Python代码三、仿真结果及分析写在后面的话 前言 首先给出使用复数指数函数生成正弦函数和余弦函数的数学表达式&#xff0c;然后给出Python仿真代码&#xff0c;并绘制了生成的函数图形&#xff0c;最后给出…

ChatGPT任务设计和微调策略的优化

目录 ChatGPT任务设计和微调策略的优化 一、GPT-3的基础 二、任务设计和微调策略的优化 三、基于人类反馈的强化学习(RLHF) 举例 完全注意力机制的自回归解码器网络 一、定义与原理 二、举例说明 ChatGPT任务设计和微调策略的优化 ChatGPT确实是从GPT-3开始,通过任…

基于统计方法的语言模型

基于统计方法的语言模型 基于统计方法的语言模型主要是指利用统计学原理和方法来构建的语言模型&#xff0c;这类模型通过分析和学习大量语料库中的语言数据&#xff0c;来预测词、短语或句子出现的概率。 N-gram模型&#xff1a;这是最基础的统计语言模型之一&#xff0c;它基…

解决中文乱码问题:常见原因与解决方案

大家好&#xff0c;我是G探险者。 最近开发遇到了中文乱码问题&#xff0c;在本地环境我导入一个json文件到系统后&#xff0c;中文显示正常&#xff0c;但是我们的项目部署在华为云的容器之后&#xff0c;发现&#xff0c;同样的操作&#xff0c;导入的数据&#xff0c;最终显…

微积分复习笔记 Calculus Volume 1 - 4.7 Applied Optimization Problems

4.7 Applied Optimization Problems - Calculus Volume 1 | OpenStax

一七五、HTML 不同类型的事件及其说明和示例

HTML 事件处理程序是通过 JavaScript 来捕获和响应不同的用户操作、系统事件或浏览器事件。下面是不同类型的事件及其说明和示例。 Window 事件 1. onresize 当浏览器窗口的大小发生变化时触发。 <!DOCTYPE html> <html lang"en"> <head><m…

前端预览word、excel、ppt

看到很多人都是用微软 Office Web Viewer https://view.officeapps.live.com/op/view.aspx?src[文件链接]&#xff0c; 但是我们内网访问不到&#xff0c;不说废话了&#xff0c;上代码 1.预览word、excel&#xff08;vue-office/docx、vue-office/excel&#xff09; //预览…