Java Setter返回此vs生成器
我想知道,当构造一个对象时,setter返回Java Setter返回此vs生成器,java,builder,Java,Builder,我想知道,当构造一个对象时,setter返回this之间有什么区别吗: 具有ID(字符串名称)的公共用户{ this.name=名称; 归还这个; } 和一个构建器(例如,由IDEA插件生成的构建器) 我的第一印象是,一个二传手返回这个要好得多: 它使用更少的代码-生成器没有额外的类,在对象构造结束时没有build()调用 它读起来更好: newuser().withName(“Some Name”).withAge(30); vs User.UserBuilder.anUserBuild
this
之间有什么区别吗:
具有ID(字符串名称)的公共用户{
this.name=名称;
归还这个;
}
和一个构建器(例如,由IDEA插件生成的构建器)
我的第一印象是,一个二传手返回这个要好得多:
- 它使用更少的代码-生成器没有额外的类,在对象构造结束时没有
build()
调用
- 它读起来更好:
newuser().withName(“Some Name”).withAge(30);
vs
User.UserBuilder.anUserBuilder().withName(“某些名称”).withAge(30.build();
那为什么要使用builder呢?有什么我遗漏的吗?构建器是设计模式,用于为代码提供清晰的结构。它们还经常用于创建不可变的类变量。您还可以在调用build()
方法时定义前置条件。这取决于类的性质。如果您的字段不是final
(即,如果类可以是可变的),则执行以下操作:
new User().setEmail("alalal@gmail.com").setPassword("abcde");
User.newBuilder().withEmail("alalal@gmail.com").withPassowrd("abcde").build();
或者这样做:
new User().setEmail("alalal@gmail.com").setPassword("abcde");
User.newBuilder().withEmail("alalal@gmail.com").withPassowrd("abcde").build();
。。。什么都不会改变
但是,如果您的字段应该是最终的
(一般来说,这是首选的,以避免对字段进行不必要的修改,当然它们不必是可变的),那么构建器模式可以保证在设置所有字段之前不会构建对象。
当然,您可能会获得相同的结果,即使用所有参数公开单个构造函数:
public User(String email, String password);
。。。但是,当您拥有大量参数时,在构建对象之前,能够看到您所做的每一个设置,会变得更方便、更易读。我认为您的问题更符合以下公式:
我们是在实现Builder模式时创建一个单独的Builder类,还是继续返回相同的实例
根据报告:
使用生成器模式封装产品的构造
并允许它分步骤构建
因此,封装是重要的一点
现在让我们看看您在原始问题中提供的方法的差异。主要区别在于设计,即如何实现构建器模式,即如何继续构建对象:
在ObjecBuilder独立类方法中,您不断返回构建器对象,并且在完成构建后,仅返回已完成/构建的对象(!),这是更好地封装创建过程的方法,因为它更一致且结构设计更合理,因为你有一个明显分开的两个不同的阶段:
1.1)建造对象
1.2)完成构建并返回构建实例(如果您消除了setter,这可能会使您拥有不可变的构建对象)
在从同一类型返回的示例中,您仍然可以修改它,这可能会导致类的设计不一致和不安全
构建器的一个优点是,您可以使用它来创建对象,而不必知道其精确的类-类似于您可以使用工厂的方式。想象一下,如果您想要创建一个数据库连接,但连接类在MySQL、PostgreSQL、DB2或其他类型之间有所不同,那么构建器就可以选择并实例化正确的实现类,而您实际上不需要担心它
当然,setter函数不能做到这一点,因为它要求已经实例化一个对象。关键是中间对象是否是有效实例
如果new User()
是有效的User
,并且new User().withName(“Some Name”)
是有效的User
,而new User().withName(“Some Name”).withAge(30)
是有效的用户,那么请务必使用您的模式
但是,如果您没有提供姓名和年龄,用户是否真的有效?也许,也许不是:如果这些有一个合理的默认值,可能是这样,但是名称和年龄不能真正有默认值
关于用户.Builder
的一点是中间结果不是用户
:您设置了多个字段,然后才构建用户要理解的关键是不可变类型的概念
假设我有以下代码:
public class UnitedStates {
private static final List<String> STATE_NAMES =
Arrays.asList("Washington", "Ohio", "Oregon", "... etc");
public static List<String> getStateNames() {
return STATE_NAMES:
}
}
这将起作用。现在对于所有的调用方来说,显然有一个状态叫做Turtlia
。华盛顿?什么?无处可寻
问题是数组.asList
返回一个可变对象:您可以对该对象调用一些方法来更改它
这样的对象无法与不信任的代码共享,而且由于您不记得自己写过的每一行,一两个月内您无法信任自己,因此,您基本上无法信任任何人。如果要正确编写此代码,只需使用List.of
而不是Arrays.asList
,因为List.of
生成一个不可变的对象。它有改变它的零方法。它似乎有方法(它有一个set
method!),但试着调用它。它不会起作用,你会得到一个例外,最重要的是,列表不会改变。事实上,这是不可能的。幸运的是,字符串也是不可变的
不可变的更容易推理,并且可以自由地与您喜欢的任何东西共享,而无需复制
那么,想要你自己的不可变?很好-但显然唯一的方法是创建一个构造函数,其中所有值都已设置,就是这样-不可变类型不能有set
方法
newBridge()
.name("Golden Gate")
.longestSpan(1280)
.built(1937)
.length(2737)
.build();
Bridge goldenGate = Bridge.create().withName("Golden Gate").withLength(2737);
import lombok.Value;
import lombok.Builder;
@Value @Builder
public class Bridge {
String name;
int built;
int length;
int span;
}