【设计模式】创建型模式(四):建造者模式

news2024/11/15 20:03:14

创建型模式(四):建造者模式

  • 1.概念
  • 2.案例
  • 3.优化

1.概念

建造者模式 是一种创建型设计模式,它允许你创建复杂对象的步骤与表示方式相分离。

建造者模式是一种创建型设计模式,它的主要目的是将一个复杂对象的 构建过程 与其 表示 相分离,从而可以创建具有不同表示形式的对象。

概要
说明
意图将一个复杂的构建过程与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决在软件系统中,一个复杂对象的创建通常由多个部分组成,这些部分的组合经常变化,但组合的算法相对稳定。
何时使用当一些基本部件不变,而其组合经常变化时。
如何解决将变与不变的部分分离开。
关键代码1️⃣ 建造者:创建并提供实例。
2️⃣ 导演:管理建造出来的实例的依赖关系和控制构建过程。
应用实例1️⃣ 去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出不同的 “套餐”。
2️⃣ Java 中的 StringBuilder。
优点1️⃣ 分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。
2️⃣ 可以更好地控制构建过程,隐藏具体构建细节。
3️⃣ 代码复用性高,可以在不同的构建过程中重复使用相同的建造者。
缺点1️⃣ 如果产品的属性较少,建造者模式可能会导致代码冗余。
2️⃣ 增加了系统的类和对象数量。
使用场景1️⃣ 需要生成的对象具有复杂的内部结构。
2️⃣ 需要生成的对象内部属性相互依赖。
注意事项与工厂模式的区别是:建造者模式更加关注于零件装配的顺序。

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

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

在这里插入图片描述

2.案例

我们假设一个快餐店的商业案例,其中,一个典型的 套餐 可以是一个 汉堡(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。

在这里插入图片描述

  • 1️⃣ Item.javaPacking.java:创建一个表示 食物条目食物包装 的接口。
public interface Item {
   public String name();
   public Packing packing();
   public float price();    
}
public interface Packing {
   public String pack();
}
  • 2️⃣ Wrapper.javaBottle.java:创建实现 Packing 接口的实体类。
public class Wrapper implements Packing {
 
   @Override
   public String pack() {
      return "Wrapper";
   }
}
public class Bottle implements Packing {
 
   @Override
   public String pack() {
      return "Bottle";
   }
}
  • 3️⃣ Burger.javaColdDrink.java:创建实现 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️⃣ VegBurger.javaChickenBurger.javaCoke.javaPepsi.java:创建扩展了 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.java:创建一个 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.java:创建一个 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.java: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

3.优化

我们将第 2 节中的步骤 6️⃣ 和 7️⃣ 拆解一下,使之更清晰。

  • 指导者
public class Director {    
    public void Constuct(Builder builder){        
        builder.prepareVegMeal();        
        builder.prepareNonVegMeal();    
    }
}
  • 抽象建造者
public class Builder {    
    public Meal meal = new Meal();    
    public void prepareVegMeal() {};    
    public void prepareNonVegMeal() {};    
    public Meal getMeal() { return null };
};
  • 具体建造者 1
public class VegMealBuilder extends Builder{
	@Override    
    public void prepareVegMeal() {        
        meal.addItem(new VegBurger());        
        meal.addItem(new Coke());
    }
    
    @Override    
    public void prepareNonVegMeal() { }    
    
    @Override
    public Meal getMeal() {        
        return meal;    
    }
}
  • 具体建造者 2
public class NonVegMealBuilder extends Builder {    
    @Override    
    public void prepareVegMeal() { }    
    
    @Override    
    public void prepareNonVegMeal() {        
        meal.addItem(new ChickenBurger());        
        meal.addItem(new Pepsi());    
    }    
   
    @Override   
    public Meal getMeal() {        
        return meal;    
    }
}
  • Client
public class Test {    
    @Test    
    public void BuilderPatternDemo() {
    	// 创建指挥者        
        Director director = new Director();        
        
        // 创建建造者
        VegMealBuilder b1 = new VegMealBuilder();        
        NonVegMealBuilder b2 = new NonVegMealBuilder();        
        
        // 注入建造者,然后指挥者构建午餐
        director.Constuct(b1);        
        director.Constuct(b2);        
        
        // 获取构建好的 Meal 对象
        Meal vegMeal = b1.getMeal();        
        System.out.println("Veg Meal");        
        vegMeal.showItems();        
        System.out.println("Total Cost: " +vegMeal.getCost());        
        
        // 获取构建好的 Meal 对象
        Meal nonVegMeal = b2.getMeal();        
        System.out.println("\n\nNon-Veg Meal");        
        nonVegMeal.showItems();       
        System.out.println("Total Cost: " +nonVegMeal.getCost());    
    }
}

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

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

相关文章

极速上云2.0范式:一键智连阿里云

在传统上云的现状与挑战&#xff1a; 专线上云太重&#xff0c;VPN上云不稳&#xff0c;云上VPC&#xff0c;云下物理网络&#xff0c;多段最后一公里...... 层层对接&#xff0c;跳跳延迟&#xff0c;好生复杂! 当你试图理解SD-WAN供应商和阿里云的文档&#xff0c;以协调路由…

7-ZIP工具的功能分享:合并分卷压缩文件

在日常工作中&#xff0c;有些大文件无法单独传输&#xff0c;我们通常会通过压缩拆分成多个分卷文件来完成传输。 当完成传输后&#xff0c;不想要这么多分卷文件的时候&#xff0c;就可以通过7-ZIP工具的合并功能来解决这个问题。下面一起来看看&#xff0c;具体如何操作。 …

【C++算法】位运算

位运算基础知识 1.基础运算符 << : 左移 >> : 右移 ~ : 取反 & : 按位与&#xff0c;有0就是0 I : 按位或&#xff0c;有1就是1 ^ : 按位异或&#xff0c;&#xff08;1&#xff09;相同为0&#xff0c;相异为1&#xff08;2&#xff09;无进位相加 2.…

【docker】阿里云使用docker,2024各种采坑

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ dial tcp: lookup on 8.8.8.8:53: no such host失败属于DNS问题 2️⃣ docker镜像配置配置最新镜像源 3️⃣ 【重点】阿里云专用获取自己的镜像加速器地址配置镜像地址 &#x1f6ec; 文章小结&#x1f4d6; 参考资料 &#x…

MySQL_SQLYog简介、下载及安装(超详细)

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

如何设置xshell关闭最后一个选项卡标签时不退出软件?

不知道你是否遇到这个问题&#xff0c;就是在使用xshell的时候&#xff0c;每次关闭最后一个选项卡标签的时候&#xff0c;xshell软件默认就退出了&#xff0c;好多次我都只是想要关闭&#xff0c;而非退出&#xff0c;所以该如何设置&#xff0c;才能到我们的预期的效果呢&…

re题(23)BUUFCTF-[FlareOn4]login

BUUCTF在线评测 (buuoj.cn) 下载后打开看到是一个txt和一个html 分别打开看看&#xff0c;txt是提示&#xff0c;html应该就是要破解的网页 打开网页&#xff0c;查看源代码 找到程序&#xff0c;变灰的部分是关键&#xff0c;是指如果是前13个字母就加13&#xff0c;如果是…

手机端跑大模型:Ollma/llama.cpp/vLLM 实测对比

昨天给大家分享了&#xff1a;如何在手机端用 Ollama 跑大模型 有小伙伴问&#xff1a;为啥要选择 Ollama&#xff1f; 不用 Ollama&#xff0c;还能用啥&#xff1f;据猴哥所知&#xff0c;当前大模型加速的主流工具有&#xff1a;Ollama、vLLM、llama.cpp 等。 那我到底该…

鸿蒙版 React Native 正式开源,ohos_react_native 了解一下

距离鸿蒙 Next 宣布一年后&#xff0c;除了 Flutter 的鸿蒙支持之外&#xff0c;React Native 的社区支持的 ohos_react_native 也终于在 OpenHarmony-SIG 对外开源&#xff0c;并且和 Flutter 不同在于&#xff0c;本次开源的版本是基于 React Native 0.72.5 。 ohos_react_n…

算法——贡献法

前天的AtCoder Beginner Contest 371 D题碰到了这个贡献法&#xff0c;刚好之前的第十一届蓝桥杯省赛第二场真题AcWing 2868. 子串分值也是用的这个方法hh,但是赛时没有搞出来。。。 AcWing 2868. 子串分值 对于一个字符串 SS&#xff0c;我们定义 SS 的分值 f(S)f(S) 为 SS 中…

UDS 诊断 - TransferData(传输数据)(0x36)服务

UDS 诊断服务系列文章目录 诊断和通信管理功能单元 UDS 诊断 - DiagnosticSessionControl&#xff08;诊断会话控制&#xff09;&#xff08;0x10&#xff09;服务 UDS 诊断 - ECUReset&#xff08;ECU重置&#xff09;&#xff08;0x11&#xff09;服务 UDS 诊断 - SecurityA…

芯片制造过程(科普版)

tip&#xff1a;是搬运过来的&#xff0c;vx公众号&#xff1a;胖虎说可科普(感觉它的视频也是不知道哪里搞过来的&#xff0c;bushi) 目录 1 芯片结构2 制造过程2.1 晶圆的制造2.2 晶圆的加工2.3 掩膜电路2.4 光刻2.5 离子注入2.6 切割 封装等 最后 记录一下编写过程&#xff…

IM系统完结了,那简历该怎么写?(含简历项目描述)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

在线仿真器ST-Link为例的整体认知

仿真器的作用 参考 简单来说&#xff0c;仿真器拥有下载和实时程序控制两个功能&#xff0c;而且下载的地址直接指向flash而不需要设置引脚启动单片机内部的bootloader程序&#xff0c;而实际中更加实用的是程序控制调试&#xff0c;这可以减少很多下载操作。 仿真器的在调试…

信息安全工程师(6)网络信息安全现状与问题

一、网络信息安全现状 威胁日益多样化&#xff1a;网络攻击手段不断翻新&#xff0c;从传统的病毒、木马、蠕虫等恶意软件&#xff0c;到勒索软件、钓鱼攻击、DDoS攻击、供应链攻击等&#xff0c;威胁形式多种多样。这些攻击不仅针对个人用户&#xff0c;还广泛影响企业、政府等…

[数据集][图像分类]茶叶病害分类数据集6749张7类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;6749 分类类别数&#xff1a;7 类别名称:["Unlabeled","alg…

【设计模式】UML类图和六大设计原则

前言 在实践中经常看到工厂模式、观察者模式等字眼&#xff0c;渐觉设计模式的重要性&#xff0c;于是开刷设计模式。 本文讲述了UML类图以及设计模式的六大原则 参考资料&#xff1a; 课程视频&#xff1a;黑马程序员Java设计模式 一、UML类图 1. 类和接口的表示方式 如…

【Elasticsearch系列八】高阶使用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

在线教育平台项目

介绍 基于SpringBootVue前后端分离的在线教育平台项目&#xff0c;单体应用服务架构。系统共设计三种角色&#xff1a;管理员、讲师和学员&#xff0c;三个角色分别对应一个操作端。也就是本系统1个后台项目&#xff0c;三个前端项目。管理员端没有引入角色和权限管理&#xf…

YoloV8 trick讲解

1.将 YOLOv5 的 C3结构换成了梯度流更丰富的 C2f结构: C3 C3 模块的设计灵感来自 CSPNet&#xff0c;其核心思想是将特征图的部分通道进行分割和并行处理&#xff0c;目的是减少冗余梯度信息&#xff0c;同时保持较高的网络表达能力。C3 结构与传统的残差结构类似&#xff0c;但…