设计模式之建造者模式

什么是建造者模式

建造者模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。这种模式将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

举一个简单的例子:假设我们要创建一个复杂的对象,例如一辆汽车,它由多个部分组成,包括引擎、车身、轮胎等。如果我们使用传统的创建方式,我们需要在代码中定义一个汽车类,并在其中定义各个部分的方法和属性。但是,这种方式会使得代码变得非常复杂和难以维护。

而使用建造者模式,我们可以将汽车的创建过程分解为多个步骤,每个步骤由一个独立的建造者类负责。首先,我们可以定义一个汽车接口,它规范了汽车对象的各个组成部分的建造。然后,我们可以定义具体的建造者类,它们实现了汽车接口,并具体化复杂对象各部分的创建。最后,我们可以定义一个指挥者类,它调用具体建造者来创建复杂对象的各个部分。

在上面的例子中,建造者模式将汽车的创建过程分解为多个简单的步骤,每个步骤由一个独立的建造者类负责。这样可以使得代码更加清晰和易于维护,并且可以灵活地控制对象的创建过程。

建造者模式UML类图

  1. Builder(抽象建造者):创建一个Product对象的各个部件指定的抽象接口。
  2. ConcreteBuilder(具体建造者):实现抽象接口,构建和装配各个部件。
  3. Product(产品角色):一个具体的产品对象,包含各个部件。
  4. Director(指挥者):构建一个使用Builder接口的对象,主要负责隔离了客户与对象的生产过程,控制产品对象的生产过程。

建造者模式的实现

下面以一个汽车制造为示例演示一下建造者模式的使用工厂,UML类图如下:

1、Car:小汽车的抽象接口;

2、SmallCar:小汽车的实体类,实现了Car接口;

3、Engine、Tyre、CarBody:汽车的零件,如发动机、轮胎、车身等;

4、CarBuilder:定义了汽车制造的过程;

5、GeelyCarBuilder:是CarBuilder的具体实现,实际的汽车的建造过程在这里实现;

6、CarDirector:汽车制造过程的指挥协调者,负责指挥整个汽车制造过程的顺序;

Car.java

public interface Car {/*** 展示* @return*/String show();/*** 启动*/void start();/*** 熄火*/void stop();
}

SmallCar.java

@Data
public class SmallCar implements Car {private String brand;//品牌private Engine engine;//发动机private Tyre tyre;//轮胎private CarBody carBody;//车身@Overridepublic String show() {String msg = "品牌:%s,发动机:%s,轮胎:%s,车身:%s";return String.format(msg, this.brand, this.engine.getType(), this.tyre.getType(), this.carBody.getColor());}@Overridepublic void start() {System.out.println("启动->" + this.show());}@Overridepublic void stop() {System.out.println("熄火->" + this.show());}
}

Engine.java

@Data
public class Engine {private String type;public Engine(String type) {this.type = type;System.out.println("制造发动机:"+type);}
}

Tyre.java

/*** 轮胎*/
@Data
public class Tyre {private String type;public Tyre(String type) {this.type = type;System.out.println("制造轮胎:"+type);}
}

CarBody.java

@Data
public class CarBody {private String color;public CarBody(String color) {this.color = color;System.out.println("制造车身:"+color);}
}

CarBuilder.java

public interface CarBuilder {/*** 生产发动机* @return*/Engine buildEngine(String type);/*** 生产轮胎* @return*/Tyre buildTyre(String type);/*** 生产车身* @return*/CarBody buildCarBody(String color);/*** 组装小汽车* @return*/Car build();
}

GeelyCarBuilder.java

/*** 吉利汽车厂*/
public class GeelyCarBuilder implements CarBuilder {@Overridepublic Engine buildEngine(String type) {return new Engine(type);}@Overridepublic Tyre buildTyre(String type) {return new Tyre(type);}@Overridepublic CarBody buildCarBody(String color) {return new CarBody(color);}@Overridepublic Car build() {SmallCar smallCar = new SmallCar();return smallCar;}
}

CarDirector.java

@Data
@AllArgsConstructor
public class CarDirector {private CarBuilder carBuilder;public Car constructSmallCar(String brand,String engineType,String tyreType,String carBodyColor){Engine engine = carBuilder.buildEngine(engineType);Tyre tyre = carBuilder.buildTyre(tyreType);CarBody carBody = carBuilder.buildCarBody(carBodyColor);SmallCar car = ((SmallCar) carBuilder.build());car.setEngine(engine);car.setTyre(tyre);car.setCarBody(carBody);car.setBrand(brand);System.out.println("汽车组装完成");return car;}
}

测试类

public class Test {public static void main(String[] args) {CarBuilder carBuilder=new GeelyCarBuilder();CarDirector carDirector = new CarDirector(carBuilder);Car car = carDirector.constructSmallCar("吉利汽车","国产发动机","马牌轮胎","白色");car.start();car.stop();Car car1 = carDirector.constructSmallCar("沃尔沃汽车", "沃尔沃发动机", "米其林轮胎", "黑色");car1.start();car1.stop();}
}

建造者模式的适用场景

下面总结一下建造者模式的一些适用场景:

  1. 相同的方法,不同的执行顺序,产生不同的事件结果时。
  2. 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时。
  3. 产品类非常复杂,或者产品类中调用顺序不同产生了不同的效果。
  4. 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时。

总之,建造者模式是一种通过将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示的设计模式。它可以将对象的创建过程分解为多个简单的步骤,每个步骤由一个独立的建造者类负责。这样可以使得代码更加清晰和易于维护,并且可以灵活地控制对象的创建过程。

总结

优点

  1. 封装性好,创建和使用分离。
  2. 扩展性好,建造类之间独立、一定程度上解耦。
  3. 客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。

缺点

  1. 产品的组成部分必须相同,这限制了其使用范围。
  2. 如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
  3. 可能会产生多余的Builder对象。

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

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

相关文章

【Edabit 算法 ★☆☆☆☆☆】Maximum Edge of a Triangle

【Edabit 算法 ★☆☆☆☆☆】Maximum Edge of a Triangle algorithms math numbers Instructions Create a function that finds the maximum range of a triangle’s third edge, where the side lengths are all integers. Examples nextEdge(8, 10) // 17 nextEdge(5, 7…

matlab bin格式转txt输出

matlab bin格式转txt输出 clc,clear; fid fopen(\text.bin,rb); data fread(fid,Inf,int16); fclose(fid);fidfopen(\text.txt,w); fprintf(fid,%d\n,data); fclose(fid);

vscode摸鱼插件开发

不知道大家在写代码的时候,摸不摸鱼,是不是时不时得打开一下微博,看看今天发生了什么大事,又有谁塌房,而你没有及时赶上。 为此,我决定开发一个vscode插件,来查看微博热搜 插件名称&#xff1…

influxDB学习记录

一、官网 influxdb官方英文文档:https://docs.influxdata.com/influxdb/v1.8/query_language/spec/influxdb中文文档:https://jasper-zhang1.gitbooks.io/influxdb/content/ 二、centos安装与基本配置 influxdb安装与基本配置(centos) 三…

论文阅读[51]通过深度学习快速识别荧光组分

【论文基本信息】 标题:Fast identification of fluorescent components in three-dimensional excitation-emission matrix fluorescence spectra via deep learning 标题译名:通过深度学习快速识别 三维激发-发射矩阵荧光光谱中的荧光组分 期刊与年份&…

【量化交易笔记】10.建立最简单的交易策略

概述 量化说得简单一些用策略进行股票交易,在实施交易之前,需要制定策略,并回测试共效果 为了把交易说明清楚,将这个过程,能简单,就简单,总之,简单,简单再简单。 以下主…

unity NPR 卡通渲染

文章目录 一、 介绍二、 素材准备三、 步骤四、 shader代码五、工程链接 一、 介绍 NPR是计算机图形学中的一类,即非真实感绘制(Non-photorealistic rendering),主要用于模拟艺术式的绘制风格,也用于发展新绘制风格,形式一般是卡…

owasp top 10

1、访问控制的崩溃: 通过身份验证的用户可以访问其他用户的信息,越权 达成方式:通过修改url、内部应用程序状态或html页面绕过 防范:除了公有资源外,默认情况下拒绝访问,严格判断权限,记录失败的…

冰蝎默认加密的流量解密

破解冰蝎的默认加密 流量包分析 上传的冰蝎流量包 POST /web-zh/DVWA/vulnerabilities/upload/ HTTP/1.1 Host: 192.168.197.111 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0 Accept: text/html,application/xhtmlxml,a…

Ansible定义各类变量,引用变量方式介绍及注册变量和vars_prompt的用法示例

目录 一.Ansible定义变量 1.用途 2.定义规则 3.变量优先级 二.命令行定义变量 三.定义主机和主机组变量 1.主机变量 (1)内置主机变量 (2)简单示例 2.主机组变量 四.定义playbook变量 1.通过vars表示定义变量&#xff…

HTML 实现 点击按钮切换 整张界面 点击按钮切换局部界面

点击按钮实现页面切换 点击按钮切换全局界面方法一: 使用a标签进行跳转连接 href方法二:在button标签中加上onclick属性,赋值为Javascript方法三:触发一个函数跳转方法四:表单的action定向提交跳转 点击按钮切换局部界…

shell条件测试与条件测试操作符

shell条件测试与条件测试操作符 条件测试变量#?test与条件测试语句方括号测试表达式字符串测试操作符逻辑测试操作符整数测试操作符双小括号的整数测试操作符与含义文件测试操作符条件测试举例 条件测试 条件测试是可以根据某个特定条件是否满足,来选择…

vscode调试container(进行rocksdb调试)+vscode比较git项目不同分支和fork的哪个分支

vscode调试container(进行rocksdb调试) 参考链接: https://blog.csdn.net/qq_29809823/article/details/128445308#t5 https://blog.csdn.net/qq_29809823/article/details/121978762#t7 使用vscode中的插件dev containners->点击左侧的…

zmq封装

ZmqBindlib zmq常用封装 使用方法 基本使用 1.简单请求回复 ZmqRequest request new ZmqRequest();request.RemoteAddress localaddes;request.PubClient "A";int num 0;while (true){// Thread.Sleep(1000);//string msg request.Request("hi"…

【微信小程序开发】小程序微信用户授权登录(用户信息手机号)

🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于小程序的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 授权流程讲解 一.用户信息授权登录 1.w…

MD-MTSP:粒子群优化算法PSO求解多仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、多仓库多旅行商问题MD-MTSP 多旅行商问题(Multiple Traveling Salesman Problem, MTSP)是著名的旅行商问题(Traveling Salesman Problem, TSP)的延伸,多旅行商问题定义为:给定一个𝑛座城市…

LabVIEW中管理大型数据

LabVIEW中管理大数据 LabVIEW的最大优势之一是自动内存管理。这种内存管理允许用户轻松创建字符串、数组和集群,而无需C/C用户经常担心。但是,这种内存管理设计为绝对安全,因此数据被非常频繁地复制。这通常不会造成任何问题,但是…

vue3 列表页开发【选择展示列】功能

目录 背景描述: 开发流程: 详细开发流程: 总结: 背景描述: 这个功能是基于之前写的 封装列表页 的功能继续写的,加了一个选择展示列的功能,可以随时控制表格里展示那些列的数据&#xf…

【算法教程】排列与组合的实现

数据准备 在讲排列与组合之前,我们先定义数据元素类型Fruit class Fruit{constructor(name,price){this.name namethis.price price} }排列 对N个不同元素进行排序,总共有多少不同的排列方式? Step1: 从N个元素中取1个,共N种…

Pandas 数据处理分析系列1--SeriesDataFrame数据结构详解

Pandas 概述 Pandas 是一个开源的数据分析和数据处理库,是基于 NumPy 开发的。它提供了灵活且高效的数据结构,使得处理和分析结构化、缺失和时间序列数据变得更加容易。其在数据分析和数据处理领域广泛应用,在金融、社交媒体、科学研究等领域都有很高的使用率和广泛的应用场…