建造者模式 rust和java的实现
文章目录
- 建造者模式
- 介绍
- 优点
- 缺点
- 使用场景
- 实现
- java
- rust
- rust代码仓库
建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
介绍
- 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
- 主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
- 关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
- 应用实例: 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。
建造者模式的 UML 图

java
步骤 1
创建一个表示食物条目和食物包装的接口。
Item.java
public interface Item {public String name();public Packing packing();public float price();
}
Packing.java
public interface Packing {public String pack();
}
步骤 2
创建实现 Packing 接口的实体类,方便进行不同的包装。
Wrapper.java
public class Wrapper implements Packing {@Overridepublic String pack() {return "Wrapper";}
}
Bottle.java
public class Bottle implements Packing {@Overridepublic String pack() {return "Bottle";}
}
步骤 3
创建实现 Item 接口的抽象类,该类提供了默认的功能,实现汉堡抽象和冷饮抽象的包装类。
Burger.java
public abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}@Overridepublic abstract float price();
}
ColdDrink.java
public abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}@Overridepublic abstract float price();
}
步骤 4
创建扩展了 Burger 和 ColdDrink 的实体类。
VegBurger.java
public class VegBurger extends Burger {@Overridepublic float price() {return 25.0f;}@Overridepublic String name() {return "Veg Burger";}
}
ChickenBurger.java
public class ChickenBurger extends Burger {@Overridepublic float price() {return 50.5f;}@Overridepublic String name() {return "Chicken Burger";}
}
Coke.java
public class Coke extends ColdDrink {@Overridepublic float price() {return 30.0f;}@Overridepublic String name() {return "Coke";}
}
Pepsi.java
public class Pepsi extends ColdDrink {@Overridepublic float price() {return 35.0f;}@Overridepublic String name() {return "Pepsi";}
}
步骤 5
创建一个 Meal 类,带有上面定义的 Item 对象。
Meal.java
import java.util.ArrayList;
import java.util.List;public class Meal {private List<Item> items = new ArrayList<Item>(); public void addItem(Item item){items.add(item);}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());} }
}
步骤 6
创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象。
MealBuilder.java
public class MealBuilder {public Meal prepareVegMeal (){Meal meal = new Meal();meal.addItem(new VegBurger());meal.addItem(new Coke());return meal;} public Meal prepareNonVegMeal (){Meal meal = new Meal();meal.addItem(new ChickenBurger());meal.addItem(new Pepsi());return meal;}
}
步骤 7
BuiderPatternDemo 使用 MealBuilder 来演示建造者模式(Builder Pattern)。
BuilderPatternDemo.java
public class BuilderPatternDemo {public static void main(String[] args) {MealBuilder mealBuilder = new MealBuilder();Meal vegMeal = mealBuilder.prepareVegMeal();System.out.println("Veg Meal");vegMeal.showItems();System.out.println("Total Cost: " +vegMeal.getCost());Meal nonVegMeal = mealBuilder.prepareNonVegMeal();System.out.println("\n\nNon-Veg Meal");nonVegMeal.showItems();System.out.println("Total Cost: " +nonVegMeal.getCost());}
}
步骤 8
执行程序,输出结果:
Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5
rust
因为rust的类支持组合式而不支持继承,在进行建造者构件时比java更加容易,rust的trait是支持继承的。
// rsut trait不支持重名
pub trait Item {fn name(&self)->String; fn price(&self)->f32; fn packing(&self)->String;
}// 汉堡实体类
struct ChickenBurger;
impl Item for ChickenBurger {fn name(&self)->String {String::from("ChickenBurger")}fn price(&self)->f32 {35.0}fn packing(&self)->String {String::from("Wrappper")}}
struct VegBurger;
impl Item for VegBurger {fn name(&self)->String {String::from("Pepsi")}fn price(&self)->f32 {35.0}fn packing(&self)->String {String::from("Wrappper")}
} // 饮料实体类
struct Pepsi;impl Item for Pepsi {fn name(&self)->String {String::from("Pesi")}fn price(&self)->f32 {35.0}fn packing(&self)->String {String::from("Bottle")}
}
struct Coke;impl Item for Coke {fn name(&self)->String {String::from("Coke")}fn price(&self)->f32 {35.0}fn packing(&self)->String {String::from("Bottle")}
} struct Meal {items:Vec<Box<dyn Item>>,
}
impl Meal {fn add_item<T>(&mut self,item:Box<dyn Item>) {self.items.push(item)}fn get_cost(&self)->f32{// 普通函数实现// let mut sum:f32=0.0; // for i in self.items.iter() {// let price = i.price();// sum+=price;// }// sum// 函数sjiself.items.iter().fold(0.0, |acc, x| acc + x.price())}fn show_items(&self){for i in self.items.iter() {println!("{}",i.name());println!("{}",i.packing());println!("{}",i.price());}}
}
// 添加建造者
struct MealBuilder {}
impl MealBuilder {fn prepareVegMeal()->Meal{let mut meal=Meal{items:Vec::new()};meal.add_item::<Box<dyn Item>>(Box::new(VegBurger{}));meal.add_item::<Box<dyn Item>>(Box::new(Coke{}));meal}fn prepareNonVegMeal()->Meal{let mut meal=Meal{items:Vec::new()};meal.add_item::<Box<dyn Item>>(Box::new(ChickenBurger{}));meal.add_item::<Box<dyn Item>>(Box::new(Pepsi{}));meal}
}
fn main() {let m=MealBuilder::prepareVegMeal();println!(" Veg Meal");m.show_items();println!("Total Cost : {}",m.get_cost());let m=MealBuilder::prepareNonVegMeal();println!(" \n\nNon-Veg Meal");m.show_items();println!("Total Cost : {}",m.get_cost());
}
rust代码仓库
https://github.com/onenewcode/design.git
本教程项目在bin文件夹下的builder.rs文件中
相关文章:
建造者模式 rust和java的实现
文章目录 建造者模式介绍优点缺点使用场景 实现javarust rust代码仓库 建造者模式 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。 介绍…...
书写Prompt的经验总结
首先最重要的一点是Prompt无法全部模型都通用,可能你的Prompt在ChatGPT中使用很好,迁移到ChatGLM就不行了。不知道未来是否会出现Prompt的跨平台。 首先书写Prompt要明确告诉模型要做什么,而不是告诉它不要做什么。还要保证精简,…...
WebSocket实时应用
在开发一些前端页面的时候,总是能接收到这样的需求:如何保持页面并实现自动更新数据呢?以往的常规做法,是前端使用定时轮询后端接口,获取响应后重新渲染前端页面,这种做法虽然能达到类似的效果,…...
从零开始搭建React+TypeScript+webpack开发环境-基于lerna的webpack项目工程化改造
项目背景 在实际项目中,我们的前端项目往往是一个大型的Webpack项目,结构较为复杂。项目根目录下包含了各种配置文件、源代码、以及静态资源,整体布局相对扁平。Webpack的配置文件分散在不同的部分,包括入口文件、输出目录、加载…...
网络监控系统和防火墙的区别有哪些?
现如今,市面上保护企业网络安全的设备有很多,其中使用最多的当属网络监控系统和防火墙。 网络监控系统就是通过网页内容的自动采集处理、敏感词过滤、智能聚类分类、主题检测、专题聚焦、统计分析等多个环节,实现相关网络舆情监督管理的需要…...
刷题学习记录BUUCTF
[极客大挑战 2019]RCE ME1 进入环境直接就有代码 <?php error_reporting(0); if(isset($_GET[code])){$code$_GET[code];if(strlen($code)>40){die("This is too Long.");}if(preg_match("/[A-Za-z0-9]/",$code)){die("NO.");}eval($co…...
Linux imu6ull驱动- led
一、GPIO模块结构 开始来啃手册了,打开我们的imx6ull手册。本章我们编写的是GPIO的,打开手册的第28章,这一章就有关于IMX6ULL 的 GPIO 模块结构。 mx6ull一共有5 组 GPIO(GPIO1~GPIO5) GPIO1 有 32 个引脚&…...
【 云原生 | K8S 】Kubernetes 概述
Kubernetes 概述 1 K8S 是什么? K8S 的全称为 Kubernetes (K12345678S),PS:“嘛,写全称也太累了吧,不如整个缩写”。 作用: 用于自动部署、扩展和管理“容器化(containerized)应用…...
边缘计算多角色智能计量插座:用电监测和资产管理的未来智能化引擎
目前主流的智能插座涵盖了红外遥控(控制空调和电视等带有红外标准的电器),配备着测温、测湿等仓库应用场景,配备了人体红外或者毫米波雷达作为联动控制,但是大家有没有思考一个问题,就是随着对接的深入&…...
mysql隐式转换转换引起的bug
生产环境中遇到一个情况情况 ,过滤数据发现过滤不掉相关值情况,具体情况如下 原始数据: CREATE TABLE test (id bigint(11) NOT NULL AUTO_INCREMENT COMMENT 自增id,subject_id bigint(11) NOT NULL DEFAULT 0 COMMENT 主题id,subject_nam…...
【Python】gevent模块实现协程模拟高并发
Python中GIL的存在,导致多线程一直不是很好用,相形之下,协程的优势就更加突出了。 Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。 gevent是第三方库,通过gr…...
leetcode:2485. 找出中枢整数(python3解法)
难度:简单 给你一个正整数 n ,找出满足下述条件的 中枢整数 x : 1 和 x 之间的所有元素之和等于 x 和 n 之间所有元素之和。 返回中枢整数 x 。如果不存在中枢整数,则返回 -1 。题目保证对于给定的输入,至多存在一个中…...
asp.net core mvc之模型绑定、特性约束模型绑定、模型验证(服务器/客户端/远程)
一、不用模型绑定 数据类型都是string 1、UserController.cs public class UserController : Controller {public IActionResult Register(){return View();}[HttpPost]public IActionResult DoRegister(){//不用模型绑定 以前的方法取表单数据或Url的参数//数据类型都是s…...
AI诈骗防范:保护数字社会的安全前线
引言: 在当今数字化的时代,人工智能技术在各个领域都展现了巨大的潜力,然而,正是这些技术的广泛应用也催生了新的安全隐患。近期,AIGC在聊天、写作、绘画、编程等领域表现出色,但也被用于“AI换脸”、“AI换…...
(待完善)python学习参考手册
这里写目录标题 观前浅谈:学习路线 :学习心得笔记:Step1:简单但一问不知怎么的组织语言去回答的小问题:什么是提示符?python解释器是什么?请正在阅读本文的朋友,安装一下PyCharm以及如何进行科学的省钱:Python中的命令行模式和交互模式的区别是什么?请正在阅读本文的朋友安装…...
STM32-HAL库09-CAN通讯(loopback模式)
一、所用材料: STM32F103C6T6最小系统板 STM32CUBEMX(HAL库软件) MDK5 串口调试助手 二、所学内容: 初步学习如何使用STM32的CAN通讯功能,在本章节主要达到板内CAN通讯的效果,即32发送CAN信息再在CAN接收…...
jsvascript使用dhtmlXTreeObject的loadJSONObject绘制目录树
文章目录 1,引入dhtmlXTreeObject的css和js文件2,创建一棵目录树2.1,let tree new dhtmlXTreeObject(id-dhtmltree-0, "100%", "100%", 0);2.2,设置图片根目录(后续使用到的图片都是相对于该目录…...
LeetCode 17. 电话号码的字母组合 中等
题目 - 点击直达 1. 17. 电话号码的字母组合 中等1. 题目详情1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 3. 知识与收获 1. 17. 电话号码的字母组合 中等 1. 题目详情 1. 原题链接 LeetCode 17. 电话号码的字母组合 中等 2. 题目要…...
《GPT与AI助手:技术进步与就业前景》
随着人工智能的迅速发展,像GPT(Generative Pre-trained Transformer)这样的自然语言处理技术已经广泛应用于各个领域,各个互联网公司也纷纷推出了自己的AI助手来帮助创作、交流和解决问题。这一技术的广泛应用引发了一系列关于就业…...
线性代数 | 矩阵运算 加减 数乘 矩阵的幂运算
文章目录 1 矩阵加减和数乘2 矩阵与矩阵的乘法2.1 相乘条件:看中间,取两头2.2 相乘计算方法 3 矩阵的幂3.1 观察归纳法3.2 邻项相消法3.3 化为对角 4 判断是否可逆(证明题或者要求求出逆矩阵)4.1 直接观察4.2 由定义式推得4.2.1 待…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
