Java中的生成器设计模式

Java 中的 Builder设计模式是一种创建模式,即用于创建对象,类似于 工厂方法设计模式 ,这也是创建设计模式。 在学习任何设计模式之前,我建议先找出特定设计模式要解决的问题。 众所周知, 必要性是发明的母亲。 在没有面临问题的情况下学习设计模式并不是那么有效,相反,如果您已经面临问题,那么它比起易于理解的设计模式并学习如何解决问题就容易得多。 在本Java设计模式教程中,我们将首先看到 Builder设计模式 解决了 哪些问题 ,这将为 何时使用Java中的 Builder设计模式 提供一些见解 , 这也是一个 流行的设计模式访谈问题 ,然后我们将看到Builder设计模式的示例。在Java中使用Builder模式的利弊。

Builder模式在Java中解决了什么问题

正如我之前所说的, Builder模式是一种创新的设计模式,这意味着它可以解决与对象创建有关的问题。 Java中的构造函数用于创建对象,并且可以采用创建对象所需的参数。 问题开始于可以使用许多参数创建对象时,其中一些参数可能是必需的,而其他参数则是可选的 。 考虑一个用于创建Cake的类,现在您需要一些像鸡蛋,牛奶,面粉这样的项目来创建Cake。 它们中的许多是强制性的,其中一些是可选的,例如Cherry,fruits等。如果我们要针对不同种类的蛋糕重载构造函数 ,则将有许多构造函数,甚至更糟的是,它们将接受许多参数。

问题:

1)要维护的构造函数过多。

2)容易出错,因为许多字段具有相同的类型,例如糖和黄油都放在杯子中,所以如果您传递2杯黄油,则代替2杯糖,编译器不会抱怨,但是会得到几乎没有糖的黄油蛋糕,成本很高浪费黄油。

您可以通过创建Cake并添加成分来部分解决此问题,但这会带来另一个问题,即在构建过程中使Object处于不一致状态 ,理想情况下,在创建Cake之前,该蛋糕不可用。 这两个问题都可以通过使用Java中的Builder设计模式来解决。 Builder设计模式不仅可以提高可读性,而且还可以通过显式添加成分并使对象在完全构建后可用的方式来减少出错的机会。

顺便说一下,Java中已有许多设计模式教程,例如Java中的 Decorator模式教程和Observer模式 。 如果您还没有阅读过,那么值得一读。

Java中的Builder设计模式示例

我们将使用在Java中使用Builder设计模式创建Cake的相同示例。 在这里,我们在Cake中有一个静态的嵌套生成器类 ,用于创建对象。

Java Builder设计模式准则

1)在该类中创建一个名为Builder的静态嵌套类,该类的对象将由Builder生成。 在这个例子中是Cake。

2)Builder类将具有与原始类完全相同的字段集。 3)在本示例中,Builder类将公开添加配料的方法,例如sugar()。 每个方法将返回相同的Builder对象。 每个方法调用都会丰富Builder。

4)Builder.build()方法将所有构建器字段值复制到实际类中并返回Item类的对象。

5)Item类(我们正在为其创建Builder的类)应具有私有构造函数,以通过build()方法创建其对象,并防止外部人员访问其构造函数。

public class BuilderPatternExample {public static void main(String args[]) {//Creating object using Builder pattern in javaCake whiteCake = new Cake.Builder().sugar(1).butter(0.5).  eggs(2).vanila(2).flour(1.5). bakingpowder(0.75).milk(0.5).build();//Cake is ready to eat :)System.out.println(whiteCake);}
}class Cake {private final double sugar;   //cupprivate final double butter;  //cupprivate final int eggs;private final int vanila;     //spoonprivate final double flour;   //cupprivate final double bakingpowder; //spoonprivate final double milk;  //cupprivate final int cherry;public static class Builder {private double sugar;   //cupprivate double butter;  //cupprivate int eggs;private int vanila;     //spoonprivate double flour;   //cupprivate double bakingpowder; //spoonprivate double milk;  //cupprivate int cherry;//builder methods for setting propertypublic Builder sugar(double cup){this.sugar = cup; return this; }public Builder butter(double cup){this.butter = cup; return this; }public Builder eggs(int number){this.eggs = number; return this; }public Builder vanila(int spoon){this.vanila = spoon; return this; }public Builder flour(double cup){this.flour = cup; return this; }public Builder bakingpowder(double spoon){this.sugar = spoon; return this; }public Builder milk(double cup){this.milk = cup; return this; }public Builder cherry(int number){this.cherry = number; return this; }//return fully build objectpublic Cake build() {return new Cake(this);}}//private constructor to enforce object creation through builderprivate Cake(Builder builder) {this.sugar = builder.sugar;this.butter = builder.butter;this.eggs = builder.eggs;this.vanila = builder.vanila;this.flour = builder.flour;this.bakingpowder = builder.bakingpowder;this.milk = builder.milk;this.cherry = builder.cherry;       }@Overridepublic String toString() {return "Cake{" + "sugar=" + sugar + ", butter=" + butter + ", eggs=" + eggs + ", vanila=" + vanila + ", flour=" + flour + ", bakingpowder=" + bakingpowder + ", milk=" + milk + ", cherry=" + cherry + '}';} }

输出:

Cake{sugar=0.75, butter=0.5, eggs=2, vanila=2, flour=1.5, bakingpowder=0.0, milk=0.5, cherry=0}

Java中的生成器设计模式–优点和缺点

充分利用Builder模式也有一些缺点,但是如果您查看下面的内容,优点显然超过了Builder设计模式的缺点。 无论如何,这里都没有使用Java创建对象的Builder设计模式的优缺点。

优点:

1)如果创建对象所需的字段数大于4或5,则更具维护性。


2)不太容易出错,因为由于显式方法调用,用户将知道他们正在传递的内容。
3)更健壮,因为只有完全构造的对象可供客户端使用。

缺点: 1)冗长且代码重复,因为Builder需要从Original或Item类复制所有字段。

何时在Java中使用Builder Design模式? Builder模式是一种创建模式,当构造函数中所需的参数数量通常大于4或最多5时,应使用该模式。不要与Builder和Factory模式混淆。 Builder和Factory模式之间的区别,因为Factory可以用来创建同一接口的不同实现,但是Builder与其Container类绑定在一起,并且仅返回Outer类的对象。

这就是Java中的Builder设计模式 。 我们已经了解了为什么需要构建器模式,解决了什么问题,Java中的构建器设计模式示例以及最终何时使用构建器模式的优缺点。 因此,如果您不使用伸缩构造函数模式,或者选择不使用它,那么可以使用Builder模式。
  

参考: Java中的构建器设计模式– JCG合作伙伴 Javin Paul在Javarevisited博客上的示例教程 。


翻译自: https://www.javacodegeeks.com/2012/07/builder-design-pattern-in-java.html

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

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

相关文章

验证码( 随机数)

方式一&#xff08;变色版&#xff09;&#xff1a; <html> <head><meta charset"UTF-8"/><title></title><script src"jquery-2.0.2.min.js"></script> </head> <body> <?php header("co…

单片机串行通信全解析

1.什么是串行通信&#xff1f; 串行通信&#xff08;英语&#xff1a;Serial communication&#xff09;是指在计算机总线或其他数据通道上&#xff0c;每次传输一个位元数据&#xff0c;并连续进行以上单次过程的通信方式。与之对应的是并行通信&#xff0c;它在串行端口上通过…

java type 类型,java中的泛型类型与Type接口

假设我们定义了一个Room的类&#xff0c;表示一个房间public classRoom(){}由于我们建造好房间是&#xff0c;不知道房间以后的用途&#xff0c;他可能用来住人&#xff0c;也有可能用来放货物&#xff0c;因此需要用到泛型。但是我们可能想获取Room这个房间里面进来的的东西的…

centos7下操作防火墙

引言 最近使用centos7系统比较频繁&#xff0c;在配置服务器的时候&#xff0c;总是遇到能够ping通服务器&#xff0c;但是就是没有办法访问80端口&#xff0c;这个时候我的直觉告诉我&#xff0c;肯定是防火墙的原因&#xff0c;但是使用iptables却怎么都找不到命令&#xff0…

其他团队对本团队评价的总结

我们小组在看了其他小组的评价后&#xff0c;对自己的程序有了新的看法。转载于:https://www.cnblogs.com/bk1246788/p/6879691.html

Java:使用Fork / Join框架的Mergesort

此项的目的是显示一个Fork / Join RecursiveAction的简单示例&#xff0c;而不是过多地研究合并合并的可能优化方法&#xff0c;或者比使用Exkutor / Join Pool优于现有的基于Java 6的现有实现&#xff08;例如ExecutorService&#xff09;的相对优势。 以下是使用Java的自上而…

php的异常处理方式,php异常处理基本方法

当一个php脚本运行时&#xff0c;为了防止脚本运行崩溃&#xff0c;亦或是当php作为webserver&#xff0c;为了防止php程序出错&#xff0c;抛出httpcode500错误&#xff0c;我们常常需要对php程序做异常处理。今天介绍的是最基本的异常处理方法&#xff1a;一般而言&#xff0…

关系型数据库的三范式

第一范式:确保每列的原子性. 如果每列(或者每个属性)都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式. 例如:顾客表(姓名、编号、地址、……)其中"地址"列还可以细分为国家、省、市、区等。第二范式:在第一范式的基础上更进一层,目标是确保表…

vray学习笔记(3)-多维子材质是个什么东西

多维子材质是个什么东西&#xff1f;为什么出现这个概念&#xff1f; 在3dsmax官方网站&#xff0c;我们可以看到它的定义&#xff1a; The Multi/Sub-Object material lets you assign different materials at the sub-object level of your geometry. 意思是多维子材质这个概…

Hello JavaFX 2.0:命令行介绍

我从博客文章Hello JavaFX 2.0&#xff1a;NetBeans 7.1 beta的介绍中&#xff0c;从NetBeans 7.1 beta的角度看了一个无处不在的Hello World示例的简单JavaFX版本。 在本文中&#xff0c;我将介绍仅使用命令行工具通过JavaFX实现的Hello World版本。 JavaFX 2.0 API文档包括ja…

matlab空格会消失了,如何在Matlab中自动删除保存的尾随空格?

我有同样的需求,并写了一个小脚本来做一些接近的事情.将以下内容放在MATLAB desktop shortcut中.每当您单击快捷方式按钮时,它将从编辑器中的活动文件中删除尾随空格.不如在保存时自动执行它 – 你需要记住在保存之前按下按钮 – 但差不多.测试在11b,12a和13b,但在12b也应该没问…

object to 字符串json

1 package com.beijxing.TestMain;2 3 import com.beijxing.entity.Student;4 import com.google.gson.Gson;5 import com.google.gson.annotations.SerializedName;6 7 /** 8 * 9 * author 作者 : ywp 10 * version 创建时间&#xff1a;2016年10月30日 下午9:21:33 11 */ 12…

JS 对象(Object)和字符串(String)互转

var jsObj {}; jsObj.testArray [1,2,3,4,5]; jsObj.name CSS3; jsObj.date 8 May, 2011; var str JSON.stringify(jsObj); var str1 JSON.parse(str); var str2 JSON.stringify(str1);alert(str);alert(str1); alert(str2);对象拷贝&#xff1a;var newObj JSON…

php 后退按钮事件,php – 后退按钮的会话问题

我在php文件中有这个代码,它包含在我要共享的所有页面中并保护我的页面.session_name("login");session_start();if (!isset($_SESSION[UserId])) {if(!header("Location: https://subdomain.mywebsite.com/")){ die("Unauthorized access"); }}…

异常:java lang AbstractMethodError

通常在尝试调用抽象方法时抛出此java.lang.AbstractMethodError。通常&#xff0c;此错误是在编译时本身识别的&#xff0c;如果在运行时抛出此错误&#xff0c;则该类必须不兼容&#xff08;与先前存在的类不兼容&#xff09; &#xff09;更改。因此&#xff0c;它是Incompat…

05.while循环的练习

练习1:namespace _05.while循环练习01{ class Program { static void Main(string[] args) { //打印100次"努力学习.net技术" int i 0; while (i < 100) //当i小于100就执行循环体的内容 { Console.WriteLine("{0}.努力学习.net技术",i); i; } Console…

oracle列分区,Oracle数据库分区--实例

分区表通过对分区列进行判断&#xff0c;把满足不同条件的分区列对应的记录保存在不同的分区中。一、何为分区表什么情况下会使用分区表&#xff1f;表中已有大量数据&#xff0c;或预计到表中将会保存大量的数据可以按照预期(月份、区域、dml)对表中的数据执行查询和更新什么是…

ZK实际应用:MVVM –与ZK客户端API一起使用

在之前的文章中&#xff0c;我们使用ZK的MVVM实现了以下功能&#xff1a; 将数据加载到表中 使用表单绑定保存数据 删除条目并以编程方式更新视图 ZK MVVM和ZK MVC实现方式之间的主要区别是&#xff0c;我们不直接在controller&#xff08;ViewModel&#xff09;类中访问和操…

RPC框架Dubbo分析

1&#xff0c;背景随着互联网的发展&#xff0c;网站应用的规模不断扩大&#xff0c;常规的垂直应用架构已无法应对&#xff0c;分布式服务架构以及流动计算架构势在必行&#xff0c;亟需一个治理系统确保架构有条不紊的演进单一应用架构当网站流量很小时&#xff0c;只需一个应…

定时器、计时器。

//第一种 每一秒执行一次&#xff08;重复性&#xff09;double delayInSeconds 1.0;timer dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));dispatch_source_set_timer(timer, DISPATCH_TIME_NO…