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

news2024/11/24 10:04:51

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 {
    @Override
    public String pack() {
        return "Wrapper";
    }
}
/**
 * @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接口的抽象类,该类提供默认的功能。
/**
 * @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();
}
/**
 * @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. 创建并继承 BurgerColdDrink
/**
 * @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;
    }
}
/**
 * @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;
    }
}
/**
 * @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;
    }
}
/**
 * @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 类,表示菜品实体。(产品)
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 {

    @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. 总结

使用场景

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

与抽象工厂模式的区别

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2230627.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[MySQL]DQL语句(一)

查询语句是数据库操作中最为重要的一系列语法。查询关键字有 select、where、group、having、order by、imit。其中imit是MySQL的方言&#xff0c;只在MySQL适用。 数据库查询又分单表查询和多表查询&#xff0c;这里讲一下单表查询。 基础查询 # 查询指定列 SELECT * FROM …

C/C++语言基础--C++模板与元编程系列三(变量模板、constexpr、萃取等…………)

本专栏目的 更新C/C的基础语法&#xff0c;包括C的一些新特性 前言 模板与元编程是C的重要特点&#xff0c;也是难点&#xff0c;本人预计将会更新10期左右进行讲解&#xff0c;这是第三期&#xff0c;讲变量模板、constexpr、萃取等知识&#xff1b;C语言后面也会继续更新知…

leetcode155:最小栈

设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…

探秘机器学习算法:智慧背后的代码逻辑

1、 线性回归 线性回归是预测连续变量的一种简单而有效的方法。其数学模型假设因变量 y 与自变量 x 之间存在线性关系&#xff0c;用公式表示为&#xff1a; ​ Python代码实现 import numpy as np from sklearn.linear_model import LinearRegression import matplotlib.…

Spring中@Import和@ComponentScan注解差异

首先我们定义两个类 进行Component扫描 返回结果 进行Import导入 返回 结果 可以看 我们在对该类的所有bean加载没有任何问题 结果一致 但神奇的地方在于此时 我们把Tiger类头的Component注解去掉 ComponentScan注解无法识别Tiger中的Lion Bean 删掉Component 再进行ComonentS…

Ceph 学习指南 集群部署【 cephadm 】

文章目录 引言初识 Server SANServer SAN 和传统存储对比 Ceph 概述Ceph 的架构设计Ceph 的特点Ceph 块存储Ceph 文件系统Ceph 对象存储Ceph 介绍 Ceph 集群部署配置 aliyun 源配置时间同步配置 hosts 文件安装 docker配置免密登录ceph 集群部署ceph1 配置安装 python3安装 cep…

(JVM)在JVM中,类是如何被加载的呢?本篇文章就带你认识类加载的一套流程!

在讲类加载前&#xff0c;需要先了解一下方法区、堆和直接内存三块内存区域的运行模式 1. 方法区 JVM中的方法去是所有线程中共享的一块区域 它存储了跟类相关的信息 方法区 会在虚拟机被启动时创建。它逻辑上是堆的组成部分 它在不同的jvm厂商中存在的位置可能会不同&…

【Arduino】一分钟快速在vs code 编译开发Arduino

下载Arduino 对于一些开发者来说&#xff0c;Arduino开发较为不方便&#xff0c;不管从代码的阅读性、开发效率等等方面&#xff0c;vs code都要优于Arduino IDE开发&#xff0c;而且vs code开发可以使用插件&#xff0c;比如一些AI代码插件&#xff0c;可以加快开发速率&#…

qt QDialog详解

1、概述 QDialog是Qt框架中用于创建对话框的类&#xff0c;它继承自QWidget。QDialog提供了一个模态或非模态的对话框&#xff0c;用于与用户进行交互。模态对话框会阻塞其他窗口的输入&#xff0c;直到用户关闭该对话框&#xff1b;而非模态对话框则允许用户同时与多个窗口进…

去除windows系统桌面字体的黑影

然后点开设置&#xff0c;关闭以下的2个选项

ssm034学生请假系统+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;学生请假系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本学生请假系统就是在这…

如何利用8款工具辅助建立需求管理体系

本文中&#xff0c;分享了8款辅助建立需求管理体系的工具&#xff1a;1.PingCode&#xff1b;2.Worktile&#xff1b;3.Jira&#xff1b;4.Trello&#xff1b;5.ClickUp&#xff1b;6.Notion&#xff1b;7.蓝鲸智云&#xff1b;8.红橘。 在如今快速发展的商业环境中&#xff0c…

使用Flask构建RESTful API

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Flask构建RESTful API Flask简介 环境搭建 安装Flask 项目结构 创建应用 路由定义 请求处理 获取查询参数 获取请求体 响应…

基于LLaMA Factory对LLama 3指令微调的操作学习笔记

一、环境 在vscode中用连接云服务器&#xff0c;打开文件目录。 df -h #查看盘容量 二、下载LLaMA Factory框架和数据 下载LLaMA Factory到云服务器 git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e . pip install -e .命令的含…

解决VMwareWorkstation17中CentOS7不能上网的问题

在CentOS 7中查看网络状态&#xff0c;执行命令&#xff1a; systemctl status network.service 示例如下&#xff1a; [rootlinux ~]# systemctl status network.service 发现网络错误&#xff0c;解决办法&#xff1a; [rootlinux ~]# chkconfig NetworkManager off [rootli…

UI设计公司—兰亭妙微—提供轨道交通行业UI设计

蓝蓝设计工作室2008年开始&#xff0c;2011年正式成立北京兰亭妙微科技有限公司&#xff0c;主创清华团队&#xff0c;专注软件和互联网ui设计开发&#xff0c;擅长企业信息化管理、监控、大数据软件UIUE咨询和设计开发服务。立足UI&#xff0c;一直在学习进步。交通行业UE UI解…

Linux初阶——线程(Part3):POSIX 信号量 CP 模型变体

一、什么是 POSIX 信号量 信号量本质就是一个统计资源数量的计数器。​​​​​​​ 1、PV 操作 pv操作就是一种让信号量变化的操作。其中 P 操作可以让信号量减 1&#xff08;如果信号量大于 0&#xff09;&#xff0c;V 操作可以让信号量加 1. 2、信号量类型——sem_t 3…

【C语言】预处理(预编译)详解(下)(C语言最终篇)

文章目录 一、#和##1.#运算符2.##运算符 二、预处理指令#undef三、条件编译1.单分支条件编译2.多分支条件编译3.判断符号是否被定义4.判断符号是否没有被定义 四、头文件的包含1.库头文件的包含2.本地头文件的包含3.嵌套包含头文件的解决方法使用条件编译指令使用预处理指令#pr…

ComfyUI和Photoshop相结合,PS内实现:文生图,图生图,高清放大,局部重绘,面部修复,设计师福音

本文主要介绍&#xff1a;ComfyUI和Photoshop相结合&#xff0c;一个平台实现&#xff1a;图像生成&#xff0c;放大&#xff0c;局部重绘&#xff0c;面部修复&#xff0c;实时绘画 简直是设计师的福音。 主要包括&#xff1a; Photoshop 的安装以及插件的安装 Creative Cl…

音视频入门基础:AAC专题(11)——AudioSpecificConfig简介

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;AAC…