嗨,我遇到了问题.
我想实现构建器模式以使创建对象更容易.我面临的问题与嵌套对象有关.我想要创建的对象中有一个其他对象的列表,我真的不知道如何解决它.
我希望能够执行以下操作(例如,更简单的对象):
Receipt RestaurantReceipt = new ReceiptBuilder()
.withDate("value")
.withName("value")
.AddItem("value")
.WithIngredients("value")
.WithType("value")
.AddItem("value")
.WithIngredients("value")
.WithType("value")
.build();
Run Code Online (Sandbox Code Playgroud)
或类似的东西:
Receipt RestaurantReceipt = new ReceiptBuilder()
.withDate("value")
.withName("value")
.AddItem("value", item => {
.WithIngredients("value")
.WithType("value")
})
.AddItem("value", item => {
.WithIngredients("value")
.WithType("value")
})
.build();
Run Code Online (Sandbox Code Playgroud)
示例应该代表我的情况,尽管如果有多种类型的嵌套对象.
我已经实现了一个简单的构建器模式 - 下面的代码.代码执行并运行,但构建器类中的每个'with ..'方法都会显示一条警告,其中"方法的返回值永远不会被使用"
public static class StreamParserBuilder{
//optional - have defaults:
private long spanLimit1 = 2000L;
private long spanLimit2 = 100000L;
private long spanLimit3 = 3000000L;
private String[] coordinates = {"L1", "R2"};
private String outputDirectory = System.getProperty("user.dir");
private boolean isLastSteam = false;
//required from the builder.
private String[] args;
private String inputFile;
private String streamData;
private boolean isPaired;
public StreamParserBuilder(String[] args, String inputFile, String streamData, boolean isPaired){
this.args = args;
this.inputFile = inputFile;
this.streamData = streamData;
this.isPaired = isPaired; …Run Code Online (Sandbox Code Playgroud) Builder实现Cloneable并覆盖clone(),而不是复制构建器的每个字段,不可变类保留构建器的私有克隆.这样可以轻松返回新构建器并创建不可变实例的略微修改的副本.
这样我就可以了
MyImmutable i1 = new MyImmutable.Builder().foo(1).bar(2).build();
MyImmutable i2 = i1.builder().foo(3).build();
Run Code Online (Sandbox Code Playgroud)
据说Cloneable接口有点坏了,但是这有什么违反了良好的java编码习惯,这个构造有什么问题吗?
final class MyImmutable {
public int foo() { return builder.foo; }
public int bar() { return builder.bar; }
public Builder builder() { return builder.clone(); }
public static final class Builder implements Cloneable {
public Builder foo(int val) { foo = val; return this; }
public Builder bar(int val) { bar = val; return this; }
public MyImmutable build() { return new MyImmutable(this.clone()); }
private int foo = 0; …Run Code Online (Sandbox Code Playgroud) 假设我需要一些DerivedBuilder扩展一些BaseBuilder.基础构建器有一些方法foo(返回BaseBuilder).派生构建器有方法bar.方法bar应方法之后被调用foo.为了做到这一点,我可以像这样覆盖foo方法DerivedBuilder:
@Override
public DerivedBuilder foo() {
super.foo();
return this;
}
Run Code Online (Sandbox Code Playgroud)
问题是BaseBuilder有很多方法foo,我必须覆盖它们中的每一个.我不想这样做,所以我尝试使用泛型:
public class BaseBuilder<T extends BaseBuilder> {
...
public T foo() {
...
return (T)this;
}
}
public class DerivedBuilder<T extends DerivedBuilder> extends BaseBuilder<T> {
public T bar() {
...
return (T)this;
}
}
Run Code Online (Sandbox Code Playgroud)
但问题是我还是不能写
new DerivedBuilder<DerivedBuilder>()
.foo()
.bar()
Run Code Online (Sandbox Code Playgroud)
即使T这是DerivedBuilder.为了不覆盖很多功能,我该怎么办?
Builder Pattern和Flyweight Pattern在使用方面有什么区别,因为它们都处理大量对象?
在我的一个项目中,我有两个包含DTO的包,POJO只有吸气剂和二传手.虽然重要的是它们是简单的Java bean(例如,因为Apache CXF使用它们来创建Web服务XSD等),但它也很糟糕且容易出错.
Foo foo = new Foo();
foo.setBar("baz");
foo.setPhleem(123);
return foo;
Run Code Online (Sandbox Code Playgroud)
我更喜欢流畅的接口和构建器对象,因此我使用maven/gmaven自动为DTO创建构建器.所以对于上面的代码,FooBuilder会自动生成一个,我可以像这样使用:
Foo foo = new FooBuilder()
.bar("baz")
.phleem(123)
.build();
Run Code Online (Sandbox Code Playgroud)
我还自动为生成的Builders生成单元测试.单元测试将生成上述两个代码(构建器版本和非构建器版本),并声明两个版本在equals()和的方面都是等效的hashcode().我可以实现的方法是拥有一个全局可访问的Map,其中包含每种属性类型的默认值.像这样的东西:
public final class Defaults{
private Defaults(){}
private static final Map<Class<?>, Object> DEFAULT_VALUES =
new HashMap<Class<?>, Object>();
static{
DEFAULT_VALUES.put(String.class, "baz");
// argh, autoboxing is necessary :-)
DEFAULT_VALUES.put(int.class, 123);
// etc. etc.
}
public static getPropertyValue(Class<?> type){
return DEFAULT_VALUES.get(type);
}
}
Run Code Online (Sandbox Code Playgroud)
另一个非平凡的方面是pojos有时会有收集成员.例如:
foo.setBings(List<Bing> bings)
Run Code Online (Sandbox Code Playgroud)
但在我的构建器中,我希望从这种情况生成两种方法:set方法和add方法:
fooBuilder.bings(List<Bing> bings); // set method
fooBuilder.addBing(Bing bing); // add …Run Code Online (Sandbox Code Playgroud) 我有一个(Java)类,有许多实例字段(其中许多是可选的).我希望所有字段(因此类)都是不可变的.所以,我想使用Builder Pattern来构造类的实例.
我可以使用Builder模式配置myBatis来创建类的实例吗?我知道我可以让myBatis返回一张地图并使用该地图在我的代码中构建实例.但是,我正在寻找一种方法来配置这种映射(或使用一些约定),类似于如何通过使用Java Bean和构造函数来创建实例.
编辑(包括一个例子)
这是一个例子:
package com.example.model;
// domain model class with builder
public final class CarFacts {
private final double price;
private final double numDoors;
private final String make;
private final String model;
private final String previousOwner;
private final String description;
public static class Builder {
// required params
private final double price;
private final String make;
private final String model;
// optional params
private final String previousOwner;
private final String description;
private final double numDoors;
public Builder(double …Run Code Online (Sandbox Code Playgroud) 我最近学习了Joshua Bloch的构建器模式,用于创建具有许多可选字段的对象.我多年来一直在使用类似的东西,但是直到布洛赫的书向我提出它之前,我从未使用过内部阶级.我喜欢它.
我知道另一个线程可能会在实际构建(使用build())之前更改bulider的配置,这样可能需要重新验证封闭类的构造函数中的所有值.下面是一个构建器类的示例,可以选择性地重新验证其数据.
所以我的问题是这样的:假设这是一个足够强大的设计,当所有值都有默认值时 - 知道这个类是使用默认值的不好选择 - 并且当每次设置尝试都被验证时,是否需要重新检查?虽然它可能不同,但它永远不会无效.那是对的吗?
(虽然这种设计是可管理的,但重新验证的潜在需求肯定会很复杂.老实说,我从来没有多线程,但我不想让我的库无法使用.)
谢谢你的任何建议.
/**
<P><CODE>java ReverifyBuilderInEnclosingCnstrXmpl</CODE></P>
**/
public class ReverifyBuilderInEnclosingCnstrXmpl {
public static final void main(String[] igno_red) {
//Don't reverify
ReverifyBuilderInEnclosingCnstrXmpl rvbdx = new ReverifyBuilderInEnclosingCnstrXmpl.Cfg().
name("Big Bird").age(6).build();
System.out.println(rvbdx.sName);
System.out.println(rvbdx.iAge);
//Do reverify
rvbdx = new ReverifyBuilderInEnclosingCnstrXmpl.Cfg().
reverifyInEnclosing().
name("Big Bird").age(6).build();
}
public final String sName;
public final int iAge;
/**
<P>Create a new <CODE>ReverifyBuilderInEnclosingCnstrXmpl</CODE> with defaults.</P>
**/
public ReverifyBuilderInEnclosingCnstrXmpl() {
//Does not reverify. No need.
this(new ReverifyBuilderInEnclosingCnstrXmpl.Cfg()); …Run Code Online (Sandbox Code Playgroud) 在使用构建器模式时,Java中是否存在标准实践,以确保成员变量最多设置一次.我需要确保setter被调用0或1次但从不更多.我想抛出RuntimeException一些类型,但我担心同步问题以及该领域的最佳实践.
这可能是一个非常主观的问题,但我想知道一些更多的意见.我用Spring MVC构建了一个Rest API服务,并实现了DTO-Domain-Entity模式.我想知道你对在DTO中实现Builder模式有什么看法,比如说
public class UserResponseDTO
extends AbstractResponseDTO {
private String username;
private Boolean enabled;
public UserResponseDTO(String username, Boolean enabled) {
this.username = username;
this.enabled = enabled;
}
public String getUsername() {
return this.username;
}
public Boolean getEnabled() {
return this.enabled;
}
public static class Builder {
private String username;
private Boolean enabled;
public void setUsername(String username) {
this.username = username;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public UserResponseDTO build(){
return new UserResponseDTO(username, enabled); …Run Code Online (Sandbox Code Playgroud) java design-patterns data-transfer-objects dto builder-pattern