设计模式之建造者模式(通俗易懂--代码辅助理解【Java版】)

文章目录

  • 设计模式概述
  • 1、建造者模式
  • 2、建造者模式使用场景
  • 3、优点
  • 4、缺点
  • 5、主要角色
  • 6、代码示例:
    • 1)实现要求
    • 2)UML图
    • 3)实现步骤:
      • 1)创建一个表示食物条目和食物包装的接口
      • 2)创建实现Packing接口的实体类
      • 3)创建实现 Item 接口的抽象类,该类提供了默认的功能
      • 4)创建扩展了 Burger 和 ColdDrink 的实体类
      • 5)创建一个Meal类,带有上面定义的Item对象
      • 6)创建一个MealBuilder类,实际的builder类负责创建Meal对象
      • 7)BuilderPatternDemo使用MealBuilder来演示建造者模式(Builder Pattern)
      • 8)执行程序,输出结果:
  • 7、总结

设计模式概述

创建型模式:工厂方法、抽象方法、建造者、原型、单例。
结构型模式有:适配器、桥接、组合、装饰器、外观、享元、代理。
行为型模式有:责任链、命令、解释器、迭代器、中介、备忘录、观察者、状态、策略、模板方法、访问者。
常用设计模式:
单例模式、工厂模式、代理模式、策略模式&模板模式、门面模式、责任链模式、装饰器模式、组合模式、builder模式。

1、建造者模式

  • 建造者模式是一种创建型设计模式,它允许你创建复杂对象的步骤与表示方式相分离,从而可以创建具有不同表示形式的对象。
  • 旨在通过逐步构造复杂对象的各个部分来简化对象的创建
  • 它与工厂模式的不同之处在于,建造者模式更注重将一个复杂对象的构造过程进行拆解,并且可以根据需求一步步定制地构建

2、建造者模式使用场景

  • 构造函数包含多个参数或嵌套对象且顺序不固定的对象创建:例如,像 Pizza 这样可以自定义不同配料的场景,建造者模式可以让我们有选择性地添加不同的部分,而不需要冗长的构造函数。
  • 需要可读性强的对象创建代码:对于那些复杂对象,建造者模式可以让代码更加清晰。
  • 对象的不可变性(Immutable Object):通过建造者模式,我们可以有效创建不可变对象(对象一旦创建就不可更改),这有助于避免线程安全问题。

3、优点

  • 灵活性高:可以根据不同需求构建不同的对象版本。
  • 代码清晰:由于建造者模式将对象的创建与表示分开,构建过程变得更加可读和维护。
  • 避免了构造函数过载:当构造函数包含过多参数时,使用建造者模式可以避免参数爆炸问题。

4、缺点

  • 可能增加代码复杂度:在某些场景下,如果对象并不复杂,使用建造者模式可能导致不必要的代码冗余。
  • 需要额外的Builder类:每个复杂对象都需要有一个对应的Builder类,可能会增加代码量。

5、主要角色

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

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

6、代码示例:

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。

2)UML图

在这里插入图片描述

3)实现步骤:

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 接口的抽象类,该类提供了默认的功能

public abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}@Overridepublic abstract float price();
}
public abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}@Overridepublic abstract float price();
}

4)创建扩展了 Burger 和 ColdDrink 的实体类

public class VegBurger extends Burger {@Overridepublic float price() {return 25.0f;}@Overridepublic String name() {return "Veg Burger";}
}
public class ChickenBurger extends Burger {@Overridepublic float price() {return 50.5f;}@Overridepublic String name() {return "Chicken Burger";}
}
// Coke 类继承 ColdDrink
public class Coke extends ColdDrink {@Overridepublic float price() {return 30.0f;}@Overridepublic String name() {return "Coke";}
}

// Pepsi 类继承 ColdDrink
public class Pepsi extends ColdDrink {@Overridepublic float price() {return 35.0f;}@Overridepublic String name() {return "Pepsi";}
}

5)创建一个Meal类,带有上面定义的Item对象

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对象

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)BuilderPatternDemo使用MealBuilder来演示建造者模式(Builder Pattern)

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

7、总结

建造者模式提供了一种优雅的方式来创建复杂的对象,特别适合在需要精细控制对象构建过程的场景下使用。通过分离构建过程和对象本身,它可以使代码更加简洁、可读,且易于维护。尽管它有时会增加代码的复杂度,但在应对复杂对象创建时,这种模式非常值得推荐

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

golang 字符串浅析

go的字符串是只读的 测试源代码 package mainimport ("fmt""unsafe" )func swap(x, y string) (string, string) {return y, x }func print_string(obj *string, msg string) {string_ptr : (*[2]uintptr)(unsafe.Pointer(obj))first_obj_addr : string_…

MySQL系列—13.事务

1、事务 事务是逻辑上的一组操作&#xff0c;要么都执行&#xff0c;要么都不执行。 事务控制语法 - 事务开始 begin; - 事务提交&#xff0c;提交后就会写入物理磁盘中去 commit; - 事务回滚&#xff0c;事务提交后&#xff0c;无法回滚 rollback;事务的四大特性&#xff0…

基于51单片机的温度电流电压检测系统(压力、电压、温度、电流、LCD1602)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机&#xff0c;通过DS18B20检测温度&#xff0c;滑动变阻器连接数模转换器模拟电流、电压&#xff0c;通过LCD1602显示&#xff0c;程序里设置温度阈值为40&#xff0c;电流阈值为60&am…

六西格玛咨询:石油机械制造企业的成本控制与优化专家

一、石油机械制造行业现状及主要困扰 随着全球能源需求的日益增长&#xff0c;石油开采和生产设备需求不断增加&#xff0c;石油机械制造行业在过去数十年里得到了迅猛发展。然而&#xff0c;石油机械制造作为一个高度复杂且技术密集的行业&#xff0c;也面临着多重挑战。首先…

【Vue】- 路由及传参

文章目录 知识回顾前言源码分析1. 声明式导航2. 路由传参3. 可选符4. 重定向5. 4046. 跳转及传参7. 路由懒加载拓展知识总结router-link静态传参和动态路由的对比知识回顾 前言 什么是单页面应用程序? ● 所有功能在一个html页面上实现 单页面应用优缺点? ● 优点:按需更新…

大模型时代的 AI 产品经理何去何从?

每天 LLM 相关的资讯都让人过载。作为 AI 产品经理&#xff0c;你是更兴奋呢&#xff0c;还是更担忧呢&#xff1f;整理了一下个人近期的思考&#xff0c;欢迎感兴趣的朋友一起交流。不管答案如何&#xff0c;相信我们都不应置身事外。 1 关于大模型‍‍ 大模型的各种原理讲…

OpenAI O1热度己过-如此快速的冷场带来的是人们更多对现今“AI”的思考

引入o1的瞬间辉煌 o1如耀眼的新星&#xff0c;闪耀于科技天空。发布时&#xff0c;因其思考能力而备受瞩目。它能在回答问题之前进行更多的思考&#xff0c;尤其擅长复杂推理。这种能力引发了众多用户的好奇与热情。诸如“9.8和9.11哪个大&#xff1f;”的简单问题被广泛地验证…

上海人工智能实验室开源视频生成模型Vchitect 2.0 可生成20秒高清视频

上海人工智能实验室日前推出的Vchitect2.0视频生成模型正在悄然改变视频创作的游戏规则。这款尖端AI工具不仅简化了视频制作流程&#xff0c;还为创作者提供了前所未有的灵活性和高质量输出。 Vchitect2.0的核心优势在于其强大的生成能力和高度的可定制性。用户只需输入文字描…

Java获取随机数

在Java中获取随机数通常会使用java.util.Random类或者Math.random()方法 1.java.util.Random java.util.Random类用于生成伪随机数。 // 使用无参构造方法创建Random对象Random rand new Random();// 生成一个[0, 100)范围内的随机整数int randomInt rand.nextInt(100);Sys…

算法练习题26——多项式输出(模拟)

输入格式 输入共有 2 行 第一行 1 个整数&#xff0c;n&#xff0c;表示一元多项式的次数。 第二行有 n1 个整数&#xff0c;其中第 i 个整数表示第 n−i1 次项的系数&#xff0c;每两个整数之间用空格隔开。 输出格式 输出共 1 行&#xff0c;按题目所述格式输出多项式。…

【ARM】中断的处理

ARM的异常向量表 如果发生异常后并没有exception level切换&#xff0c;并且发生异常之 前使用的栈指针是SP_EL0&#xff0c;那么使用第一组异常向量表。如果发生异常后并没有exception level切换&#xff0c;并且发生异常之 前使用的栈指针是SP_EL1/2/3&#xff0c;那么使用第…

雷朋太阳镜和AEG的制胜法宝是:音乐节以及数据驱动的品牌推广

图片来源&#xff1a;Photo by Ethan Robertson on Unsplash 几十年来&#xff0c;我们见证了流行文化偶像对大众的影响。雷朋一直是一个深受偶像和大众喜爱的品牌。借助这股浪潮&#xff0c;雷朋与全球最大的娱乐公司之一AEG合作&#xff0c;吸引消费者&#xff0c;并以沉浸式…

JAVA-集合相关

HashMap如何解决哈希冲突的&#xff1f; 计算hash值&#xff0c;基于hashCode计算冲突之后&#xff0c;先是使用链式寻址法当链表长度大于8&#xff0c;且hash表的容量大于60的时候&#xff0c;再添加元素则转化成红黑树 为什么计算hash值是&#xff0c;是将hash地址的值右移1…

推荐10款最佳的电脑监控软件,知名电脑监控软件推荐

随着互联网和科技的飞速发展&#xff0c;电脑监控软件成为企业和个人用户管理和保护信息安全的必备工具。这些软件可以帮助你实时了解电脑的使用情况、保护隐私、优化工作效率&#xff0c;甚至防止潜在的安全威胁。在这篇文章中&#xff0c;我们将为你推荐10款最佳的电脑监控软…

k8s的搭建

一、安装环境 准备三台主机&#xff1a; 192.168.1.66 k8s-master 192.168.1.77 k8s-node01 192.168.1.88 k8s-node02 网段&#xff1a; Pod ⽹段 172.16.0.0/16 Service ⽹段 10.96.0.0/16 注&#xff1a;宿主机⽹段、Pod…

乱弹篇(52)旁观者说

众所周知&#xff0c;地球人都晓得“股市是经济的晴雨表”这个定律&#xff0c;那么中秋节后的中国内地股市&#xff0c;为何在节后的9月18日首个交易日&#xff0c;上证指数仍继续下行&#xff0c;盘中还一度跌破2700点创7个多月以来新低&#xff0c;整体市场数千个股下跌呢&a…

c#进度条实现方法

在使用c#做WinFrom开发时&#xff0c;经常会用到进度条&#xff08;ProgressBar&#xff09;。那么如何才能实现winfrom进度条及进度信息提示呢&#xff1f; 方法一&#xff1a;多线程 使用c#做WinFrom开发&#xff0c;要实现进度条效果就需要用到多线程&#xff0c;如果不采…

CH1-2 误差分析

一、误差的概念 用计算机进行实际问题的数值计算时&#xff0c;往往求得的是问题的近似解&#xff0c;都存在误差。 模型误差&#xff1a;在建立数学模型过程中&#xff0c;要将复杂的现象抽象归结为数学模型&#xff0c;往往要忽略一些次要因素的影响,而对问题作一些简化&am…

Nginx越界读取缓存漏洞(CVE-2017-7529)

漏洞原理&#xff1a; 影响版本内默认配置模块的Nginx只需要开启缓存&#xff0c;攻击者可以通过发送包含恶意构造range域的header请求进行远程攻击造成信息泄露。 影响范围&#xff1a; Nginx 0.5.6 – 1.13.2 漏洞复现&#xff1a; 开启靶场&#xff0c;访问8080端口 中间…

数据处理与统计分析篇-day05-Pandas详解

创建DaraFrame对象 概述 DataFrame是一个表格型的结构化数据结构&#xff0c;它含有一组或多组有序的列&#xff08;Series&#xff09;&#xff0c;每列可以是不同的值类型&#xff08;数值、字符串、布尔值等&#xff09;。 DataFrame是Pandas中的最基本的数据结构对象&…