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

news2024/9/20 8:51:21

文章目录

  • 设计模式概述
  • 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 {
   @Override
   public String pack() {
      return "Wrapper";
   }
}

// 瓶装  Bottle.java
public class Bottle implements Packing {
   @Override
   public String pack() {
      return "Bottle";
   }
}

3)创建实现 Item 接口的抽象类,该类提供了默认的功能

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

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

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

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


// Pepsi 类继承 ColdDrink
public class Pepsi extends ColdDrink {
 
   @Override
   public float price() {
      return 35.0f;
   }
 
   @Override
   public 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.0


Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5

7、总结

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

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

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

相关文章

828华为云征文 | 深入解析华为云X实例保障云上业务安全的关键策略

前言 在云计算快速发展的背景下&#xff0c;安全问题一直是企业上云过程中关注的焦点。随着数据迁移至云端&#xff0c;企业对云计算平台的安全性能提出了更高要求&#xff0c;特别是如何防止数据泄露、网络攻击、以及确保合规性等问题至关重要。华为云作为全球领先的云服务提供…

分类预测|基于哈里斯鹰优化最小二乘支持向量机的数据分类预测Matlab程序HHO-LSSVM多特征输入多类别输出

分类预测|基于哈里斯鹰优化最小二乘支持向量机的数据分类预测Matlab程序HHO-LSSVM多特征输入多类别输出 文章目录 一、基本原理1. 哈里斯鹰优化算法&#xff08;HHO&#xff09;2. 最小二乘支持向量机&#xff08;LSSVM&#xff09;HHO-LSSVM模型流程总结 二、实验结果三、核心…

2024/9/12 408“回头看”之文件元数据和索引节点

文件元数据&#xff1a; 索引节点&#xff1a; 把所有文件元数据放在一起&#xff0c;其中只保存文件名和索引节点号&#xff0c;然后通过索引节点来指向其他信息&#xff1a; 索引节点放在外存。 未采用索引节点&#xff1a;找目录项得一个磁盘块、一个磁盘块的找&#xff…

通用四期ARM架构银河麒麟桌面操作系统V10【安装、配置FTP客户端】

一、操作环境 服务端&#xff1a;银河麒麟桌面操作系统V10SP1 客户端&#xff1a;银河麒麟桌面操作系统V10SP1 二、服务端配置 注&#xff1a;以下命令均在终端执行 鼠标点击桌面右键&#xff0c;选择打开终端 操作步骤&#xff1a; 1、安装vsftpd软件&#xff1a;如果提…

【运维监控】Prometheus+grafana+kafka_exporter监控kafka运行情况

本示例通过kafka_exporter收集kafka的监控指标&#xff0c;然后将数据收集到prometheus中&#xff0c;最后通过grafana的dashboard导入模板进行可视化。本示例分为四个部分&#xff0c;即prometheus、grafana部署、kafka_exporter部署与配置和最后的集成。说明&#xff1a;本示…

智科python毕业设计方向汇总

文章目录 &#x1f6a9; 1 前言1.1 选题注意事项1.1.1 难度怎么把控&#xff1f;1.1.2 题目名称怎么取&#xff1f; 1.2 开题选题推荐1.2.1 起因1.2.2 核心- 如何避坑(重中之重)1.2.3 怎么办呢&#xff1f; &#x1f6a9;2 选题概览&#x1f6a9; 3 项目概览题目1 : 深度学习社…

12、xinference部署与自定义模型

1、环境创建 创建虚拟环境 conda create --name xinference python3.10.9激活虚拟环境 conda activate xinference2、安装文件 官网&#xff1a;https://inference.readthedocs.io/zh-cn/latest/getting_started/installation.html pip install "xinference[transfor…

DM数据库报错集合

DM数据库报错集合 DMHS安装部署报错 Oracle端的报错 启动dmhs时失败并报错 解决方法&#xff1a;这里就是没有密钥key&#xff0c;需要拥有DM数据库对应的key&#xff0c;然后将其命名为dmhs.key&#xff0c;并放在dmhs安装路径的bin目录下&#xff0c;就可直接运行 Orac…

经典任务损失函数与评价指标

损失函数_Lcm_Tech的博客-CSDN博客 1. 回归任务损失函数&#xff08;MAE、MSE&#xff09; 【损失函数】MSE, MAE, Huber loss详解_mse损失函数-CSDN博客 【回归损失函数】L1&#xff08;MAE&#xff09;、L2&#xff08;MSE&#xff09;、Smooth L1 Loss详解_mae损失函数-CS…

Qt连接mysql数据库---kalrry

Qt连接mysql数据库---kalrry 前言解决方法1解决方法2 前言 Qt自带SQLite数据库驱动很好用&#xff0c;但如果甲方要求必须使用MySql&#xff0c;那么坑就来了(本教程在Qt5版本下测试成功&#xff0c;Qt6需要自行尝试) 以下是记录解决Qt连接mysql的驱动问题 解决方法1 使用my…

企业需要多少六西格玛绿带?

在探讨企业的六西格玛绿带专业人员需求时&#xff0c;我们需要理解这个术语的背景和含义。六西格玛是一种质量改进方法&#xff0c;通过数据驱动的方法来解决过程问题和提高效率。六西格玛绿带是一种专业技能的认证&#xff0c;代表了对于六西格玛方法的深入理解和实践经验。 在…

超声波清洗机洗眼镜效果好吗?超声波清洗机洗眼镜推荐

眼镜是我们日常生活中不可或缺的伙伴。然而&#xff0c;在长时间使用之后&#xff0c;眼镜上往往会沾染各种污垢&#xff0c;这些污渍不仅影响视觉效果&#xff0c;还可能引起眼部不适。因此&#xff0c;清洁眼镜显得尤为重要。幸运的是&#xff0c;有了超声波清洗机这一工具&a…

春招审核新策略:Spring Boot系统实现

3系统分析 3.1可行性分析 通过对本大学生入学审核系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本大学生入学审核系统采用Spring Boot框架&#xff0c;JA…

树形结构-数据结构

一、基本知识 树&#xff1a;一对多的树形结构顶层的结点&#xff1a;称为根节点叶子结点&#xff08;终端结点&#xff09;&#xff1a;最外围的结点&#xff0c;只有前驱结点&#xff0c;没有后继结点的结点&#xff0c;其结点的度是0分支结点&#xff1a;分支点是描述数据结…

金山在线文档编辑器

官方文档地址&#xff1a;快速开始-WebOffice 知识库 首先按照文档写的方式将包引入项目了 util.js import WebOfficeSDK from "../../public/JSEditor/open-jssdk-v0.0.13.umd" export function WordSDK(url, isEdit, mountDom, isShowTopArea, isShowHeader) {c…

【HTML】HTML页面和常见标签

文章目录 什么是前端HTML 页面编写如何快速生成代码框架常见标签注释标签标题标签段落标签换行标签格式化标签 什么是前端 Web 前端&#xff0c;用来直接给以用户呈现的一个一个的网页。一个软件通常是由 后端前端 完成的 后端&#xff1a;通过 Java/C等语言&#xff0c;完成相…

机械厂选并联电容器的要求

在机械厂选择并联电容器时&#xff0c;需要考虑多个因素&#xff0c;以确保无功补偿设备能够有效提高功率因数、降低电网损耗、提升电能质量。以下是机械厂选用并联电容器时的一些关键要求&#xff1a; 1、容量选择 无功功率需求&#xff1a;根据机械厂的负载特性&#xff0c;…

Apple公众号,是如何玩转SVG擦出/刷新/填涂特效?|E2.COOL黑科技SVG编辑器

动画类型 width/height animation 通过擦出/刷新等效果&#xff0c;实现产品的多图轮播、细节对比、文字高亮——这是 Apple 公众号特别偏爱的一种 SVG 交互设计方式。那么它的技术本质是什么&#xff1f;Apple 的编辑又是如何持续创新应用在 SVG 图文内的&#xff1f;本期我…

【Python】谷歌浏览器总是自动更新,使用selenium跟chromedriver版本不匹配怎么办?

我发现&#xff0c;我的电脑对谷歌浏览器的禁止自动更新无效&#xff0c;哪怕是在任务计划程序里&#xff0c;禁止谷歌浏览器更新&#xff0c;也没有用。而且有时候点开右上角的三个点&#xff0c;也会自动更新版本。 但是往往chromedriver的更新版本更不上浏览器的版本哇&…

SQL Server数据库简单的事务日志备份恢复

模拟数据库备份恢复过程 1.基础操作 1.创建TestDB数据库&#xff0c;并添加数据 USE [master] GO CREATE DATABASE TestDB CONTAINMENT NONE ON PRIMARY ( NAME NTestDB, FILENAME ND:\TestDB.mdf , SIZE 8192KB , MAXSIZE UNLIMITED, FILEGROWTH 65536KB ) LOG ON ( …