建造者模式深入理解:演示建造单个和多个产品的实践,结合模板模式,通俗易懂

首先呢看下建造者的定义是什么样的,先读一遍

建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它主要用于将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表现形式。这种模式通过一系列可重用的独立的类(称为建造者或构建器)来一步一步创建一个复杂的对象,而不需要知道具体的内部构造细节

优缺点

建造者模式的主要优点

  1. 封装性好:通过建造者将产品的各个部件和组装过程封装起来,客户端无需了解产品内部的具体构造细节,只需指定需要的产品类型和配置即可。
  2. 扩展性好:由于每个具体建造者都是相互独立的,因此新增一种产品或者变更已有产品的构建方式时,只需要新增或修改相应的建造者类,不影响其他部分代码,从而实现系统的松耦合。
  3. 便于控制构建过程:在构建过程中,可以根据需要逐步细化构造步骤,灵活地控制产品的创建过程,甚至支持动态决定构建部件的数量和顺序。
  4. 便于并行构造:在某些场景下,不同部分的构建可以独立进行,有利于提高系统性能,特别是在多线程环境下的构建。

建造者模式的主要缺点

  1. 增加类的数量:引入建造者模式会增加额外的类,包括抽象建造者、具体建造者和可能的导演类等,增加了系统的复杂性和理解难度。
  2. 内部修改困难:一旦产品结构较为复杂,对于产品内部细节的改动可能会导致多个建造者的相关逻辑都需要调整,维护成本相对较高。
  3. 过度设计风险:如果对象结构比较简单,或者变化不多,使用建造者模式可能会显得过于复杂,不适用于简单对象的构建。
    总结来说,建造者模式非常适合用于创建具有多重构造参数或组合选项的复杂对象,尤其当这些选项的不同组合可能导致大量微小差异的产品实例时,该模式能够很好地管理和组织这些复杂性。

网图来一张
在这里插入图片描述
好了,直接上代码,这里我们先构建一个CarProduct,很多描述都写在了对应的注释中了啊,这里就不过多赘述

package com.mtgg.laoxiang.service.example.designer.builder;import lombok.Data;/*** 要构建的产品对象*/
@Data
public class CarProduct {private String partA;private String partB;private String partC;
}
package com.mtgg.laoxiang.service.example.designer.builder;/*** 建造者抽象类*/
public abstract class Builder {//建造产品时,实例化,相当于统一放到一个地方,product相当于一个封装,里面可以放各种东西的组成protected CarProduct carProduct = new CarProduct();//建造,建造各种东西然后set到product中public abstract void builderPartA();public abstract void builderPartB();public abstract void builderPartC();//提供获得产品的入口,要获得这个产品,就调用这个方法public CarProduct getResult() {return carProduct;}}

上面定义了产品,构造器,获取产品的方法,下面这个就是构造器要具体干的活了

package com.mtgg.laoxiang.service.example.designer.builder;public class BJBuilder extends Builder{@Overridepublic void builderPartA() {System.out.println("构建个1球");carProduct.setPartA("1球");}@Overridepublic void builderPartB() {System.out.println("构建个2球");carProduct.setPartB("2球");}@Overridepublic void builderPartC() {System.out.println("构建个3球");carProduct.setPartC("3球");}
}
package com.mtgg.laoxiang.service.example.designer.builder;public class HZBuilder extends Builder{@Overridepublic void builderPartA() {System.out.println("构建个1香蕉");carProduct.setPartA("1香蕉");}@Overridepublic void builderPartB() {System.out.println("构建个2香蕉");carProduct.setPartB("2香蕉");}@Overridepublic void builderPartC() {System.out.println("构建个3香蕉");carProduct.setPartC("3香蕉");}
}

指挥者来了,指挥我到底想要啥,什么数量,什么顺序,定义几个图纸来交给构造器去构造,然后main使用的时候直接调用这个定义好的流程,就能拿到对应的产品

package com.mtgg.laoxiang.service.example.designer.builder;/*** 指挥者* 控制生成流程*/
public class Director {//这个抽象类可以定义成全局变量,也可以定义接口,此处可以引用接口,更不违反原则private Builder builder;/*** 注入builder*/private Director(Builder builder) {this.builder = builder;}/*** 控制流程,此处类似使用模板模式*/public CarProduct construct2(){builder.builderPartC();builder.builderPartA();return builder.getResult();}public CarProduct construct(){builder.builderPartB();builder.builderPartA();builder.builderPartC();return builder.getResult();}public static void main(String[] args) {//此处可选择不同的建造者建造产品Director director = new Director(new HZBuilder());CarProduct construct = director.construct();System.out.println(construct);director = new Director(new BJBuilder());CarProduct construct1 = director.construct2();System.out.println(construct1);}}

*构建个2香蕉
构建个1香蕉
构建个3香蕉
Product(partA=1香蕉, partB=2香蕉, partC=3香蕉)
构建个3球
构建个1球
Product(partA=1球, partB=null, partC=3球) *

在这里插入图片描述

如果我想建造另外一个对象呢?难道类似的类都要加一份?那肯定是low的,做法如下,

可以加具体建造,定义好要建造的东西,再建一个指挥者方法,尽量不要在原来的方法上改,改造后如下

假如有另一个对象PhoneProduct

@Data
public class PhoneProduct {private String pa;private String pb;private String pc;
}

Builder中加上要构建的这个产品,并加个返回产品的方法,所以这么看的话那几个构建的抽象方法就不能太个性化,最好抽象一些,像是定义三四个工厂一样,具体怎么生产看子类实现

public abstract class Builder {//建造产品时,实例化,相当于统一放到一个地方,product相当于一个封装,里面可以放各种东西的组成//另外一个产品protected PhoneProduct phoneProduct = new PhoneProduct();
……………………public PhoneProduct getPhoneResult() {return phoneProduct;}
}

好了我们定义一个子类去构建具体的内容,不用改另外一个对象的构建,保证对扩展开放,对修改关闭

public class XMBuilder extends Builder{@Overridepublic void builderPartA() {System.out.println("小米a");phoneProduct.setPa("pa");}@Overridepublic void builderPartB() {System.out.println("小米b");phoneProduct.setPb("pb");}@Overridepublic void builderPartC() {System.out.println("小米c");phoneProduct.setPc("pc");}
}

指挥者我们改造一下,构建顺序以及数量都可以抽出来共用,只需要定义construct2或constructPhone方法,指定模板,返回产品就OK了,想要啥产品要啥产品

public class Director {//这个抽象类可以定义成全局变量,也可以定义接口,此处可以引用接口,更不违反原则private Builder builder;/*** 注入builder*/private Director(Builder builder) {this.builder = builder;}/*** 构建模板 定义构建顺序以及内容*/public void buildTemplateA(){builder.builderPartB();builder.builderPartA();builder.builderPartC();}/*** 构建模板 定义构建顺序以及内容*/public void buildTemplateB(){builder.builderPartC();builder.builderPartA();}/*** 构建以及获取car产品的入口*/public CarProduct construct2(){this.buildTemplateB();return builder.getResult();}//不同形态的car产品public CarProduct construct(){this.buildTemplateA();return builder.getResult();}//这个是构建和获取phone产品的入口public PhoneProduct constructPhone(){this.buildTemplateA();return builder.getPhoneResult();}public static void main(String[] args) {//此处可选择不同的建造者建造产品Director director = new Director(new HZBuilder());CarProduct construct = director.construct();System.out.println(construct);director = new Director(new BJBuilder());CarProduct construct1 = director.construct2();System.out.println(construct1);//构建另外一个产品,使用时指定用XMBuilder这个厂家生产的就行director = new Director(new XMBuilder());PhoneProduct construct2 = director.constructPhone();System.out.println(construct2);}}

下面这是执行结果

构建个2香蕉
构建个1香蕉
构建个3香蕉
CarProduct(partA=1香蕉, partB=2香蕉, partC=3香蕉)
构建个3球
构建个1球
CarProduct(partA=1球, partB=null, partC=3球)
小米b
小米a
小米c
PhoneProduct(pa=pa, pb=pb, pc=pc)

祝你好运!~~

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

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

相关文章

编程笔记 html5cssjs 040 CSS盒子模型

编程笔记 html5&css&js 040 CSS盒子模型 一、CSS 盒子模型二、元素的宽度和高度三、最终元素的总宽度四、元素的总高度五、练习小结 网页是靠分成不同的块,再赋予这些块各不相同的属性来布局的。所以这个“块”是一个基础。先看块本身的构造。 一、CSS 盒子…

深度学习笔记(四)——使用TF2构建基础网络的常用函数+简单ML分类实现

文中程序以Tensorflow-2.6.0为例 部分概念包含笔者个人理解,如有遗漏或错误,欢迎评论或私信指正。 截图和程序部分引用自北京大学机器学习公开课 TF2基础常用函数 1、张量处理类 强制数据类型转换: a1 tf.constant([1,2,3], dtypetf.floa…

网络传输文件软件哪个好?企业该如何选择?

随着互联网技术的飞速发展,网络传输文件软件已经成为企业日常工作中不可或缺的一部分。然而,在市场上众多的网络传输文件软件中,很多企业对于如何选择合适的方案感到困惑。那么,究竟什么是网络传输文件软件?它有哪些作…

怎么注册微商城?开启微商城之旅

在这个数字化时代,微商城的出现为商家提供了一个全新的机会,商家企业可以通过微商城来展示和销售自己的产品。而对于一些商家而言,不知道怎么注册微商城。下面给大家做一个简单的分享。 第一步:选择合适的微商城搭建工具 在注册…

计算机毕业设计 | SpringBoot宠物店管理系统(附源码)

1,绪论 项目背景 我国已经成为世界第二大经济体,经济实力高速发展以及百姓生活水平的普遍提高,不断地要求企业提供更加多元化的娱乐方式,更加快速和方便的服务,因此对宠物行业也提出了更加严格的要求,如管…

洛谷 P1523 旅行商简化版【线性dp+npc问题简化版】

原题链接:https://www.luogu.com.cn/problem/P1523 题目背景 欧几里德旅行商(Euclidean Traveling Salesman)问题也就是货郎担问题一直是困扰全世界数学家、计算机学家的著名问题。现有的算法都没有办法在确定型机器上在多项式时间内求出最优解,但是有…

二叉树(完全二叉树,满二叉树,二叉树的特性,遍历方式,根据遍历方式画出完整的二叉树图相关例题)

目录 基本概念 一、二叉树(满二叉树,完全二叉树) 二、二叉树的特性 1、若规定根节点的层数为1,则一棵非空二叉树的第i层最多有2^(i-1) 个节点(i>0) 2、若规定只有根节点的二叉树的深度为1&#xff0…

人力资源智能化管理项目(day01:基础架构拆解)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学,可以点心心支持一下哈 一、基础架构拆解 1.拉取模板代码 git clone GitHub - PanJiaChen/vue-admin-template: a vue2.0 minimal admin template 项目名 2.core-js…

使用WAF防御网络上的隐蔽威胁之SQL注入攻击

SQL注入攻击是一种普遍存在且危害巨大的网络安全威胁,它允许攻击者通过执行恶意的SQL语句来操纵或破坏数据库。 这种攻击不仅能够读取敏感数据,还可能用于添加、修改或删除数据库中的记录。因此,了解SQL注入攻击的机制及其防御策略对于保护网…

6.3.1认识Camtasia4(1)

6.3.1认识Camtasia4 安装完Camtasia4(本书使用Camtasia4.0.1版本)后,单击【开始】|【程序】|【Camtasia Studio 4】|【Camtasia Studio】,启动Camtasia Studio,启动后界面如图6-3-1所示。 图6-3-1 Camtasia Studio界面 Camtasia Studio窗口中…

打印的前后顺序

面试题经常会有 <script>console.log(1)setTimeout(function(){console.log(2)})console.log(3)let pnew Promise((resolve,reject) >{console.log(4)resloved(hhhhhh)})p.then(res >{console.log(res)console.log(5)},res >{console.log(7)})console.log(6)&l…

Git版本控制——分支

分支 几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着可以把工作从开发主线上分离开来进行重大的Bug修改、开发新的功能&#xff0c;以免影响开发主线。 查看本地分支 git branch创建本地分支 git branch 分支名切换分支(checkout) git checkout 分支名创建…

Python源码26:海龟画图turtle画向日葵

---------------turtle源码集合--------------- Python教程43&#xff1a;海龟画图turtle画小樱魔法阵 Python教程42&#xff1a;海龟画图turtle画海绵宝宝 Python教程41&#xff1a;海龟画图turtle画蜡笔小新 Python教程40&#xff1a;使用turtle画一只杰瑞 Python教程39…

萌宠宠物用品商城设计与制作-计算机毕业设计源码79718

摘要 在社会快速发展的影响下&#xff0c;宠物商城继续发展&#xff0c;大大增加了宠物用品的数量、多样性、质量等等的要求&#xff0c;使宠物用品商城的管理和运营比过去十年更加困难。依照这一现实为基础&#xff0c;设计一个快捷而又方便的萌宠宠物用品商城是一项十分重要并…

通过旋转机械臂,将机械臂上相机拍摄图像的任意点移动至图像中心的方法

计算原理 角度计算 相机CCD大小固定&#xff0c;即相机成像平面大小固定&#xff0c;相机视场角(FOV)仅由相机焦距F决定&#xff1b; 因此&#xff0c;定焦相机的FOV大小固定&#xff0c;通过上图可以看出相机视场角的计算公式为&#xff1a; FOV 2*atan&#xff08;w/2f&…

四、任意文件读取漏洞

一、介绍 解释&#xff1a;任意文件读取漏洞就其本身来说就是&#xff0c;攻击者绕过网站防御者设置的防御&#xff0c;读取到了正常使用者不应该读取到的内容。网站开发者使用不同的语言&#xff0c;任意文件读取漏洞利用方式就不同。 二、不同开发语言的不同漏洞点 1.PHP …

编译与链接(C/C++)

在C/C中关于代码的运行需要经过.c文件到.exe文件&#xff0c;而其中走过这些步骤这需要对原始的.c文件进行编译与链接。对于编译与链接主要构成了翻译环境&#xff0c;经过翻译环境之后生成.exe文件&#xff0c;然后在通过运行环境输出对应的结果。本篇主要讲解编译与链接。 以…

ElasticSearch扫盲概念篇[ES系列] - 第500篇

历史文章&#xff08;文章累计500&#xff09; 《国内最全的Spring Boot系列之一》 《国内最全的Spring Boot系列之二》 《国内最全的Spring Boot系列之三》 《国内最全的Spring Boot系列之四》 《国内最全的Spring Boot系列之五》 《国内最全的Spring Boot系列之六》 E…

KT148A语音芯片智能锁扩展语音地址以及如何支持大量小文件的打包

一、语音芯片应用于智能锁的需求 智能锁的语音播放需求中&#xff0c;有很多需要多国语言合并在一起的需求 其中语音文件数多&#xff0c;并且每个语音文件小的特点 如果使用OTP的语音芯片&#xff0c;就很麻烦&#xff0c;因为用户不可烧录&#xff0c;调试也很繁琐 同时大…

算法竞赛备赛进阶之数位DP训练

数位DP的思想就是对每一位进行DP&#xff0c;计算时记忆化每一位可以有的状态&#xff0c;其作用是减少运算时间&#xff0c;避免重复计算。 数位DP是一种计数用的DP&#xff0c;一般就是要统计一个区间[A,B]内满足一些条件数的个数。 以1e9甚至1e18、1e100的问题为例&#x…