Java 设计模式——建造者模式

目录

  • 1.概述
  • 2.结构
  • 3.实例
    • 3.1.产品类
    • 3.2.抽象建造者类
    • 3.3.具体建造者类
    • 3.4.指挥者类
    • 3.5.测试
  • 4.优缺点
  • 5.使用场景
  • 6.模式扩展
  • 7.创建者模式对比

1.概述

建造者模式 (Builder Pattern) 是一种创建型设计模式,用于创建复杂对象。它将对象的构建过程分离成独立的部分,同时允许按照不同的方式构建对象。通常情况下,当一个对象的构建过程有多个步骤,且这些步骤可以按照不同的顺序来构建时,建造者模式就非常有用。通过将构建逻辑封装到具体的建造者类中,客户端可以使用相同的构建过程来创建不同类型的对象。

2.结构

建造者模式包含如下角色:

  • 抽象建造者类 (Builder):这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的部件对象的创建。
  • 具体建造者类 (ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。
  • 产品类 (Product):要创建的复杂对象。
  • 指挥者类 (Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。类图如下:
    在这里插入图片描述

3.实例

【例】创建共享单车:生产自行车是一个复杂的过程,它包含了车架,车座等组件的生产。而车架又有碳纤维,铝合金等材质的,车座有橡胶,真皮等材质。对于自行车的生产就可以使用建造者模式。这里 Bike 是产品,包含车架,车座等组件;Builder 是抽象建造者,MobikeBuilder 和 OfoBuilder 是具体的建造者;Director 是指挥者。类图如下:
在这里插入图片描述
具体代码如下:

3.1.产品类

Bike.java

public class Bike {private String frame;//车架private String seat;//车座public String getFrame() {return frame;}public void setFrame(String frame) {this.frame = frame;}public String getSeat() {return seat;}public void setSeat(String seat) {this.seat = seat;}
}

3.2.抽象建造者类

Builder.java

public abstract class Builder {//声明Bike类型的变量,并进行赋值protected Bike bike = new Bike();public abstract void buildFrame();public abstract void buildSeat();//构建自行车的方法public abstract Bike createBike();
}

3.3.具体建造者类

MobileBuilder.java

//具体的构建者,用来构建摩拜单车对象
public class MobileBuilder extends Builder{public void buildFrame() {bike.setFrame("碳纤维车架");}public void buildSeat() {bike.setSeat("真皮车座");}public Bike createBike() {return bike;}
}

OfoBuilder.java

public class OfoBuilder extends Builder{public void buildFrame() {bike.setFrame("铝合金车架");}public void buildSeat() {bike.setSeat("橡胶车座");}public Bike createBike() {return bike;}
}

3.4.指挥者类

Director.java

public class Director {//声明 builder 类型的变量private Builder builder;public Director(Builder builder) {this.builder = builder;}//组装自行车的功能public Bike construct() {builder.buildFrame();builder.buildSeat();return builder.createBike();}
}

3.5.测试

Client.java

public class Client {public static void main(String[] args) {//创建指挥者对象Director director = new Director(new MobileBuilder());//让指挥者只会组装自行车Bike bike = director.construct();System.out.println(bike.getFrame());System.out.println(bike.getSeat());}
}

注意:上面示例是 Builder 模式的常规用法,指挥者类 Director 在建造者模式中具有很重要的作用,它用于指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,但是有些情况下需要简化系统结构,可以把指挥者类和抽象建造者进行结合。

// 抽象 builder 类
public abstract class Builder {protected Bike mBike = new Bike();public abstract void buildFrame();public abstract void buildSeat();public abstract Bike createBike();public Bike construct() {this.buildFrame();this.BuildSeat();return this.createBike();}
}

4.优缺点

(1)建造者模式具有以下几个优点:

  • 分离构建过程和表示:建造者模式可以将一个复杂对象的构建过程与它的表示分离,使得相同的构建过程可以创建不同的表示。这样可以使代码结构更清晰,易于阅读和维护。
  • 隐藏产品内部细节:建造者模式将对象的构建过程封装在具体的建造者类中,使得客户端可以不需要知道产品的内部实现细节,只需要关注如何组装和使用产品。
  • 提供更好的控制:由于建造者模式将构建过程分步进行,可以通过指定不同的具体建造者,实现不同的构建过程。这样就可以更灵活地控制构建过程,根据需要定制复杂对象的创建方式。

(2)建造者模式的一些缺点包括:

  • 增加了代码量:引入建造者模式会增加额外的代码量,因为需要定义抽象建造者和具体建造者类,以及指挥者类等。对于简单的对象构建过程,可能会显得繁琐。
  • 对客户端的要求高:客户端需要显式地创建指挥者对象,并指定具体的建造者,且需要了解建造者类的接口和使用方法。这对于不熟悉建造者模式的开发人员来说可能会增加学习成本。

综上所述,建造者模式在创建复杂对象时具有很多优点,但也需要在实际应用中权衡其优缺点来决定是否使用。

5.使用场景

(1)建造者模式适用于以下几种场景:

  • 当对象的构建过程比较复杂,需要有多个步骤或者按照不同的顺序构建时,可以使用建造者模式。例如,创建一个包含多个部分的电子产品,每个部分的构建方式可能不同,而且可以按照不同的顺序组装。
  • 当需要创建的对象有多个不同的表示或配置时,可以使用建造者模式。使用不同的具体建造者可以创建不同的对象表示,而且可以在运行时动态地选择具体建造者。
  • 当想要隔离产品的构造和表示细节,使得构造过程和最终的产品解耦时,可以使用建造者模式。客户端只需要关注构建过程和产品的使用,而不需要关注产品的内部实现细节。
  • 当需要创建一系列相似但稍有差异的对象时,可以使用建造者模式。通过复用相同的构建逻辑和变化的部分,可以高效地创建多个对象。
  • 当需要在一个对象的构建过程中能够灵活地修改构建方式或者增加更多的构建步骤时,可以使用建造者模式。具体建造者的实现可以根据需求进行扩展和修改,而不会影响到客户端代码。

(2)需要注意的是,如果对象的构建过程相对简单,没有多个步骤或者差异很小,或者只有少数几个属性需要设置,那么使用建造者模式可能会显得过于繁琐,可以考虑使用其他创建型模式或者简化构建过程。

6.模式扩展

建造者模式除了上面的用途外,在开发中还有一个常用的使用方式,就是当一个类构造器需要传入很多参数时,如果创建这个类的实例,代码可读性会非常差,而且很容易引入错误,此时就可以利用建造者模式进行重构
(1)重构前代码如下:
Phone.java

public class Phone {private String cpu;private String screen;private String memory;private String mainboard;public Phone(String cpu, String screen, String memory, String mainboard) {this.cpu = cpu;this.screen = screen;this.memory = memory;this.mainboard = mainboard;}@Overridepublic String toString() {return "Phone{" +"cpu='" + cpu + '\'' +", screen='" + screen + '\'' +", memory='" + memory + '\'' +", mainboard='" + mainboard + '\'' +'}';}
}

Client.java

public class Client {public static void main(String[] args) {//构建Phone对象Phone phone = new Phone("麒麟","三星屏幕","金士顿","华硕主板");System.out.println(phone);}
}

上面在客户端代码中构建Phone对象,传递了四个参数,如果参数更多,那么代码的可读性会变差,以及使用的成本会变高。

(2)重构后代码如下:
Phone.java

public class Phone {private String cpu;private String screen;private String memory;private String mainboard;private Phone(Builder builder) {cpu = builder.cpu;screen = builder.screen;memory = builder.memory;mainboard = builder.mainboard;}public static final class Builder{private String cpu;private String screen;private String memory;private String mainboard;public Builder(){}public Builder cpu(String val){cpu = val;return this;}public Builder screen(String val){screen = val;return this;}public Builder memory(String val){memory = val;return this;}public Builder mainboard(String val){mainboard = val;return this;}public Phone build(){return new Phone(this);}}@Overridepublic String toString() {return "Phone{" +"cpu='" + cpu + '\'' +", screen='" + screen + '\'' +", memory='" + memory + '\'' +", mainboard='" + mainboard + '\'' +'}';}
}

Client.java

public class Client {public static void main(String[] args) {//构建Phone对象Phone phone = new Phone.Builder().cpu("麒麟").memory("金士顿").screen("三星屏幕").mainboard("华硕").build();System.out.println(phone);}
}

重构后的代码在使用起来更方便,某种程度上也可以提高开发效率。从软件设计上,对程序员的要求比较高。

7.创建者模式对比

(1)工厂方法模式 VS 建造者模式
工厂方法模式注重的是整体对象的创建方式;而建造者模式注重的是部件构建的过程,意在通过一步一步地精确构造创建出一个复杂的对象。

(2)抽象工厂模式 VS 建造者模式

  • 抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。
  • 建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。

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

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

相关文章

浅谈如何成为一名优秀教师

你是不是也有一个梦想,想要成为一位优秀的教师,让孩子们如沐春风,收获满满?那么,今天就让我来给你分享一下成为优秀教师的秘诀吧! 热爱教育,点燃激情 成为优秀教师,首先要有对教育的…

install pnpm : 无法加载文件的解决办法

问题描述 我在使用pnpm的时候报错 PS D:\emss\pure-admin-backend> pnpm install pnpm : 无法加载文件 C:\Users\RD-16\AppData\Roaming\npm\pnpm.ps1。未对文件 C:\Users\RD-16\AppData\Roaming\npm\pnpm.ps1 进行数字签名。无法在当前系统上运 行该脚本。有关运行脚本和设…

揭秘:如何精准定位性能瓶颈,优化系统性能?

你好,我是小濠,目前在一家准一线互联网大厂做测试开发工程师。对于一般公司普通测试工程师来说,可能性能测试做的并不是很复杂,可能只是编写下脚本,做个压测,然后输出报告结果,瓶颈分析和调优的…

软件测试 | MySQL 主键约束详解:保障数据完整性与性能优化

📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…

Python武器库开发-前端篇之CSS基本语法(三十)

前端篇之CSS基本语法(三十) CSS简介 CSS(层叠样式表)是一种用于描述网页外观和布局的样式表语言。它与 HTML 一起,帮助开发者对网页进行美化和布局。CSS通过定义网页元素的颜色、字体、大小、背景、边框等属性,使网页变得更加美…

scipy 笔记:scipy.spatial.distance

1 pdist 计算n维空间中观测点之间的成对距离。 scipy.spatial.distance.pdist(X, metriceuclidean, *, outNone, **kwargs) 1.1 主要参数 X一个m行n列的数组,表示n维空间中的m个原始观测点metric使用的距离度量out输出数组。如果非空,压缩的距离矩阵…

基于springboot实现学生成绩管理系统项目【项目源码+论文说明】

基于springboot实现学生成绩管理系统演示 摘要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生&am…

IDEA中JDK21控制台打印的中文乱码

IDEA中,使用的JDK21,控制台打印中文乱码,解决办法是重装了一下JDK。 我之前安装的版本是“jdk-21_windows-x64_bin.exe”,我配置了多个JDK环境,所以使用的是安装文件进行安装的。这次解决乱码问题,我重新安…

禁止指定电脑程序运行的2种方法

你可能要问了,为什么要禁止电脑程序运行呢,因为有的公司要净化公司的工作环境,防止某些刺头员工在公司电脑上瞎搞。也有部分家长,是为了防止自己家的孩子利用电脑乱下载东西。 今天就分享2种禁止指定电脑程序运行的方法&#xff1…

微信小程序-跳转到另一个小程序

微信小程序-跳转到另一个小程序 微信小程序跳转到另一个小程序有一个条件:这两个小程序被同一个微信公众号关联,否则不能跳转,会报错。 官方文档 wx.navigateToMiniProgram({appId: wxa38r249405b957c6,path: pages/splash/index,//extraData: 需要传递…

电子学会C/C++编程等级考试2022年03月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:温度统计 现有一段时间的温度数据,请统计指定温度出现的次数。 时间限制:1000 内存限制:65536输入 第一行一个整数n,表示温度数据的个数。(0 < n ≤ 200) 第二行n个整数,以空格分隔,每个整数表示一个温度,温度的范围大…

如何开发有趣而富有创意的营销小游戏

在数字化时代&#xff0c;企业通过创意而独特的方式与目标受众互动&#xff0c;已成为提高品牌知名度和用户参与度的重要手段之一。其中&#xff0c;设计一款引人入胜的营销小游戏&#xff0c;不仅能吸引用户的眼球&#xff0c;还能有效传达品牌信息。以下是一些建议&#xff0…