问题
我想创建一个带有fluent builder的类,两者都可以继承和扩展。基类应该有所有公共(public)和必填字段,子类应该有不同的可选字段
下面的简单示例(我能想到的最好、最简单的用例;p)
base: Animal
name
age
static Builder
impl: Snake extends Animal
length
static Builder extends Animal.Builder
impl: Spider extends Animal
numberOfLegs
static Builder extends Animal.Builder
我想以其中一种方式使用它(最喜欢的是第一种):
Spider elvis = Spider.name("elvis").age(1).numberOfLegs(8).build();
Spider elvis = Spider.builder().name("elvis").age(1).numberOfLegs(8).build();
Spider elvis = new Spider.Builder().name("elvis").age(1).numberOfLegs(8).build();
我要实现的是
- 此构建器的用户必须提供一些最少的信息(这样系统才能正常工作),否则他将无法构建该对象
- 所有可选字段都可以在必填字段之后声明,没有特定顺序
- 我可能需要为 child 添加一些必填字段,但只需更改构建器中调用的第一个方法即可轻松处理
- 我不想在这些类之外进行任何强制转换(此处:在 Main 中),但我不介意在这段代码中(此处:在 Animal 或 Spider 中)
到目前为止我失败了,如果你能帮我找到解决办法,我将不胜感激:) 还是我应该考虑一种不同的方法?
我使用的最有值(value)的资源
http://blog.crisp.se/2013/10/09/perlundholm/another-builder-pattern-for-java
http://egalluzzo.blogspot.com/2010/06/using-inheritance-with-fluent.html
Generic fluent Builder in Java
到目前为止完成的工作
到目前为止的代码可以在下面找到。有一些我尝试和失败的痕迹,有一些未使用或只是奇怪的东西(最好的例子是 IBuildImpl)。留下这些是为了让您了解我的尝试,但如果您认为这需要适度 - 请告诉我,我会清理它们
基地
package fafafa;
public abstract class Animal<T> {
String name; //mandatory field, one of many
Integer age; //mandatory field, one of many
public String getName() {
return name;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
interface IName {
IAge name(String name);
}
interface IAge {
IBuild age(Integer age);
}
interface IBuild<T extends Animal<T>> {
T build();
}
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>
implements IName, IAge, IBuild<T> {
protected T objectBeingBuilt;
protected abstract B that();
protected abstract T createEmptyObject();
Builder(){
this.objectBeingBuilt = createEmptyObject();
System.out.println();
}
@Override
public IAge name(String name) {
objectBeingBuilt.name = name;
return that();
}
@Override
public IBuild age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
// @Override
// public T build() {
// return objectBeingBuilt;
// }
}
}
实现
package fafafa;
public class Spider extends Animal<Spider> {
Integer numberOfLegs; //optional field, one of many
private Spider() {
}
public Integer getNumberOfLegs() {
return numberOfLegs;
}
@Override
public String toString() {
return "Spider{" +
"numberOfLegs='" + numberOfLegs + '\'' +
"} " + super.toString();
}
// public static Builder<Spider, Builder> name(String name) {
// return (Builder) new Builder().name(name);
// }
interface INumberOfLegs {
IBuild numberOfLegs(Integer numberOfLegs);
}
interface IBuildImpl extends IBuild<Spider>, INumberOfLegs {
@Override
Spider build();
}
public static class Builder extends Animal.Builder<Spider, Builder> implements IBuildImpl {
@Override
protected Builder that() {
return this;
}
@Override
protected Spider createEmptyObject() {
return new Spider();
}
public IBuild numberOfLegs(Integer numberOfLegs) {
objectBeingBuilt.numberOfLegs = numberOfLegs;
return that();
}
public Spider build() {
return objectBeingBuilt;
}
}
}
主要
package fafafa;
public class Main {
public static void main(String[] args) {
Spider build = new Spider.Builder().name("elvis")
.age(1)
.numberOfLegs(8) //cannot resolve method numberOfLegs
.build();
System.out.println(build);
}
}
最佳答案
看起来像代码中的许多泛型,我试着稍微简化一下。
动物
package come.stackoverflow.builder;
public abstract class Animal {
private final String name; //mandatory field, one of many
private final Integer age; //mandatory field, one of many
Animal(final String name, final Integer age) {this.name = name; this.age = age;}
public String getName() {return name;}
public Integer getAge() {return age;}
@Override public String toString() {return String.format("Animal {name='%s', age='%s'}'", name, age);}
interface IBuild<T> {
T build();
}
public abstract static class AnimalBuilder<B extends AnimalBuilder, T extends Animal> implements IBuild<T> {
String name;
Integer age;
public B name(final String name) {this.name = name; return (B) this;}
public B age(final Integer age) {this.age = age; return (B) this;}
}
}
蜘蛛
package come.stackoverflow.builder;
public class Spider extends Animal {
private final Integer numberOfLegs; //optional field, one of many
private Spider(final String name, final Integer age, final Integer numberOfLegs) {super(name, age); this.numberOfLegs = numberOfLegs;}
public Integer getNumberOfLegs() {return numberOfLegs;}
@Override public String toString() {return String.format("Spider {numberOfLegs='%s'}, %s", getNumberOfLegs(), super.toString());}
public static class SpiderBuilder extends AnimalBuilder<SpiderBuilder, Spider> {
Integer numberOfLegs;
public SpiderBuilder numberOfLegs(final Integer numberOfLegs) {this.numberOfLegs = numberOfLegs; return this;}
public Spider build() {return new Spider(name, age, numberOfLegs);}
}
}
主要测试
import come.stackoverflow.builder.Spider;
public class Main {
public static void main(String[] args) {
Spider build = new Spider.SpiderBuilder()
.name("elvis").numberOfLegs(8).age(1)
.build();
System.out.println(build);
}
}
执行结果:
蜘蛛 {numberOfLegs='8'},动物 {name='elvis', age='1'}'
关于java - 如何在 Java 中实现具有继承性的 Fluent Builder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41047524/