设计模式——建造者(Builder)模式

建造者模式(Builder Pattern),又叫生成器模式,是一种对象构建模式 它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可 以构建它们,用户不需要知道内部的具体构建细节。

简单来说,建造者模式允许你按步骤创建复杂的对象,同时将对象的构建与其表示分离。

主要解决的问题是当创建一个复杂对象时,如果直接在代码中进行对象的创建和初始化,会导致代码变得复杂而难以维护。

而建造者模式通过将对象的构建过程委派给不同的建造者,使得代码更加清晰、可读,并且可以灵活地构建不同的对象表示形式。

当我们需要创建一个对象,但该对象具有复杂的构建过程,并且构建过程可以有不同的表示形式时,可以考虑使用建造者模式。

建造者模式包含4个元素:

  • 抽象建造者(Builder):一个抽象接口,规范了产品对象的各个组成成分的建造。
  • 具体建造者(ConcreteBuilder):与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。
  • 导演者(Director):调用具体建造者角色来创建产品对象。
  • 产品(Product):一般是一个较为复杂的对象。

优点包括:

  1. 将对象的构建过程封装在一个建造者类中,使得客户端代码与具体构建过程解耦,提高了代码的可维护性和可读性。
  2. 可以灵活地构建不同表示形式的对象,通过调整建造者的步骤和配置,可以得到不同的对象。
  3. 可以更好地控制对象的构建过程,避免了在代码中直接创建和初始化对象的复杂性。

缺点包括:

  1. 建造者模式增加了代码的复杂性,因为需要定义多个类来实现构建者和产品对象,可能会增加项目的工程复杂性。
  2. 如果产品的属性发生变化,需要修改构建者类和产品类,可能会引起一定的维护成本。

注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

案例

我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。

我们将创建一个表示食物条目(比如汉堡和冷饮)的 Item 接口和实现 Item 接口的实体类,以及一个表示食物包装的 Packing 接口和实现 Packing 接口的实体类,汉堡是包在纸盒中,冷饮是装在瓶子中。

然后我们创建一个 Meal 类,带有 ItemArrayList 和一个通过结合 Item 来创建不同类型的 Meal 对象的 MealBuilderBuilderPatternDemo 类使用 MealBuilder 来创建一个 Meal

建造者模式的 UML 图

步骤 1

创建一个表示食物条目和食物包装的接口。

public interface Item {
   public String name();
   public Packing packing();
   public float price();    
}

public interface Packing {
   public String pack();
}

步骤 2

创建实现 Packing 接口的实体类。

public class Wrapper implements Packing {
 
   @Override
   public String pack() {
      return "Wrapper";
   }
}
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";
   }
}
public class Coke extends ColdDrink {
 
   @Override
   public float price() {
      return 30.0f;
   }
 
   @Override
   public String name() {
      return "Coke";
   }
}
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

BuiderPatternDemo 使用 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

总结

建造者模式是一种创建型设计模式,用于将复杂对象的构建过程与其表示分离。它通过将复杂对象的构建过程分解为多个简单的步骤来实现。在Java中,我们可以使用建造者模式来创建复杂对象,并且可以根据需要使用不同的建造者来创建不同的表示。建造者模式的优点包括可重用性和易于维护和扩展,但它的缺点是代码结构较为复杂。建造者模式适用于需要创建多个相似对象,或者需要在不同的上下文中创建不同的对象表示的情况。如果需要创建的对象较为简单,可能会使用建造者模式变得过于繁琐。

总之,建造者模式是一种非常有用的设计模式,可以帮助我们更好地管理对象的构建过程,并且使得代码更加易于维护和扩展。如果你需要创建一个复杂的对象,或者需要在不同的上下文中创建不同的对象表示,建议你考虑使用建造者模式来实现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python文件操作教程,Python文件操作笔记

文件的打开与关闭 想一想&#xff1a; 如果想用word编写一份简历&#xff0c;应该有哪些流程呢&#xff1f; 打开word软件&#xff0c;新建一个word文件写入个人简历信息保存文件关闭word软件 同样&#xff0c;在操作文件的整体过程与使用word编写一份简历的过程是很相似的…

使用 BERT 进行文本分类 (01/3)

摄影&#xff1a;Max Chen on Unsplash 一、说明 这是使用 BERT 语言模型的一系列文本分类演示的第一部分。以文本的分类作为例&#xff0c;演示它们的调用过程。 二、什么是伯特&#xff1f; BERT 代表 来自变压器的双向编码器表示。 首先&#xff0c;转换器是一种深度学习模…

【Linux命令详解 | gzip命令】 gzip命令用于压缩文件,可以显著减小文件大小

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 基本压缩和解压2. 压缩目录3. 查看压缩文件内容4. 测试压缩文件的完整性5. 强制压缩6. 压缩级别7. 与其他命令结合使用8. 压缩多个文件9. 自动删除原文件 总结 简介 在Linux中&#xff0c;gzip命令是一款强大的文…

C语言笔试训练【第九天】

文章目录 &#x1f47f;1、下列程序的输出是&#xff08; &#xff09;&#x1f48e;2、二维数组X按行顺序存储&#xff0c;其中每个元素占1个存储单元。若 X[4][4] 的存储地址为 Oxf8b82140 , X[9][9] 的存储地址为 Oxf8b8221c ,则 X[7][7] 的存储地址为&#xff08; &#xf…

交换实验一

题目 交换机上接口配置 SW1 interface GigabitEthernet0/0/1 port hybrid tagged vlan 2 port hybrid untagged vlan 3 to 6 interface Ethernet0/0/2 port hybrid pvid vlan 3 port hybrid untagged vlan 2 to 6 interface Ethernet0/0/3 port link-type access port d…

C++基础语法——继承

1.继承是什么&#xff1f; 继承是一种面向对象编程的概念&#xff0c;它允许一个类&#xff08;称为子类或派生类&#xff09;从另一个类&#xff08;称为基类或父类&#xff09;继承属性和方法。继承使得子类能够使用基类已有的代码&#xff0c;并且可以在此基础上进行扩展或修…

99页4万字XX大数据湖项目建设方案

导读&#xff1a;原文《99页4万字XX大数据湖项目建设方案》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 目 录 1.项目综述 1.1.项目背景 1.2.项目目标 1.3.项…

Error = [Microsoft][SQL Server Native Client 10.0]无法打开 BCP 主数据文件(已解决)

需求&#xff1a;分页方式查出表中数据存入excel中&#xff0c;并给excel标记不同的编号 前提&#xff1a; #all_4表中数据已准备好 版本&#xff1a; sql server 2008 declare n int set n 1 while n 100 begin print n:print nEXEC master.dbo.sp_configure show adva…

什么是flexbox布局?它有什么特点和优势?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是 Flexbox 布局&#xff1f;⭐ 特点和优势⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那…

(三)行为模式:1、责任链模式(Chain of Responsibility Pattern)(C++示例)

目录 1、责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;含义 2、责任链模式的UML图学习 3、责任链模式的应用场景 4、责任链模式的优缺点 5、C实现责任链模式的实例 1、责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;含义 责任…

2682. 找出转圈游戏输家

题目描述&#xff1a; n 个朋友在玩游戏。这些朋友坐成一个圈&#xff0c;按 顺时针方向 从 1 到 n 编号。从第 i 个朋友的位置开始顺时针移动 1 步会到达第 (i 1) 个朋友的位置&#xff08;1 < i < n&#xff09;&#xff0c;而从第 n 个朋友的位置开始顺时针移动 1 步…

vue之动态表单(优化)

代码资源在这儿 ↑ vue之动态表单优化 vue2js动态表单优化vue3ts动态表单优化 vue2js动态表单优化 效果图 目录结构 五个文件的完整代码: 以下是App.vue <template><div><router-view></router-view><Formpage /></div> </templa…

jenkins 安装nodejs 14

参考&#xff1a; jenkins容器安装nodejs-前端问答-PHP中文网

在ubuntu+cpolar+rabbitMQ环境下,实现mq服务端远程访问

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

LangChain手记 Agent 智能体

整理并翻译自DeepLearning.AILangChain的官方课程&#xff1a;Agent&#xff08;源代码可见&#xff09; “人们有时会将LLM看作是知识库&#xff0c;因为它被训练所以记住了来自互联网或其他地方的海量信息&#xff0c;因而当你向它提问时&#xff0c;它可以回答你的问题。有一…

网络

mcq Java 传输层&#xff1a;拆分和组装&#xff0c;完成端到端的消息传递&#xff0c;流量控制&#xff0c;差错控制等 网络层&#xff1a; 寻址、路由&#xff0c;复用&#xff0c;拥塞控制&#xff0c;完成源到宿的传递。 显然A选项是错误的&#xff0c;有流量控制的是传输层…

JavaWeb框架:Spring MVC介绍

Spring MVC 概述 概述 MVC&#xff08;Model View Controller&#xff0c;模型-视图-控制器&#xff09;&#xff0c;作为一种设计模式&#xff0c;用于应用程序的分层开发。 Spring MVC&#xff0c;由 Spring 框架提供的基于 MVC 设计模式的一个轻量级 Web 开发框架。Spring…

基于CentOS 7 部署社区版Haproxy

HAProxy是法国开发者 威利塔罗(Willy Tarreau) 在2000年使用C语言开发的一个开源软件&#xff0c;是一款具 备高并发(一万以上)、高性能的TCP和HTTP负载均衡器&#xff0c;支持基于cookie的持久性&#xff0c;自动故障切换&#xff0c;支 持正则表达式及web状态统计。 目录 1…

微服务-Fegin

在之前我们两服务之间调用的时候用的是restTemplate,但是这个方式调用存在很多的问题 String url "http://userservice/user/" order.getUserId(); 代码可读性差&#xff0c;编码体验不统一参数复杂的url难以维护 所以我们大力推出我们今天的主角--Fegin Feign是…

解决“warning: #223-D: function “xPortSysTickHandler“ declared implicitly“告警提示

继上篇文章发布已有时隔两个月之久&#xff0c;今天就把这两个月遇到的一些问题解决分享一下&#xff0c;首先&#xff0c;我们来看今天分享的这个关于我在学习freertos遇到的一个告警。如图所示&#xff1a; 告警提示原句为&#xff1a; warning: #223-D: function "xP…