Java 使用抽象生成器扩展抽象类与使用具体类和具体生成器
我想在我即将完成的一些工作中使用builder模式,这些工作在层次结构中有几个类。基类将至少有9个字段要开始,不同的子类可以分别添加2-4个更多的字段。这将很快失去控制,基于这个确切的原因,builder模式对我很有吸引力。我在书和文章中初步接触到了建设者模式。他们很有帮助,但对如何扩展这种模式一无所知。我试图自己实现这个,但是我遇到了每个子类的构造函数的问题,因为我不知道如何将生成器中收集的数据传递给超类。我一直在寻找答案,下面是我的发现 本文给出了如何使用抽象生成器扩展抽象类的示例。这也是基于此 我喜欢这个示例,因为它允许您轻松地扩展这些类,但在我看来,这也违背了使用生成器模式的目的,因为方法Java 使用抽象生成器扩展抽象类与使用具体类和具体生成器,java,generics,inheritance,design-patterns,builder,Java,Generics,Inheritance,Design Patterns,Builder,我想在我即将完成的一些工作中使用builder模式,这些工作在层次结构中有几个类。基类将至少有9个字段要开始,不同的子类可以分别添加2-4个更多的字段。这将很快失去控制,基于这个确切的原因,builder模式对我很有吸引力。我在书和文章中初步接触到了建设者模式。他们很有帮助,但对如何扩展这种模式一无所知。我试图自己实现这个,但是我遇到了每个子类的构造函数的问题,因为我不知道如何将生成器中收集的数据传递给超类。我一直在寻找答案,下面是我的发现 本文给出了如何使用抽象生成器扩展抽象类的示例。这也是基
withS(String s)
和withI(int I)
的行为很像setter方法。此外,此方法将基类和生成器类的字段保留为受保护的字段,而不是私有字段
这是我的一个
我意识到你不能像我在这里展示的那样实例化一个对象,但是还有其他的方法吗?这可能是工厂要去的地方吗?也许我只是对构建器模式的总体假设有误。:)如果是这样的话,有更好的方向吗?你的第一个例子不错,但我认为这不是你想要的 我仍然有点不确定你到底想要什么,但是看到你的例子不适合你,我想我会给你一两个我自己的例子 任何新类型,都会有自己的生成器,接受其父级的生成器。 如您所见,这类似于:
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
在你的例子中
然而,这也很快失去控制,变量和子类的数量越来越多
另一种选择是使用动态变量,请看以下内容:
马丁·福勒(Martin Fowler)写了一篇很好的文章,详细说明了所有的利弊
无论如何,这是我的第二个例子:
public class Demo {
public static void main(String[] args) {
ConcreteBuilder builder = new ConcreteBuilder();
Concrete concrete = builder.with("fourth", "valueOfFourth").build();
for(String value : concrete.getAttributes().values())
System.out.println(value);
}
}
class ConcreteBuilder{
private Concrete concrete;
public ConcreteBuilder(){
concrete = new Concrete();
}
public ConcreteBuilder with(String key, String value){
concrete.getAttributes().put(key, value);
return this;
}
public Concrete build(){
return concrete;
}
}
class Concrete{
private HashMap<String, String> attributes;
public Concrete(){
attributes = new HashMap<>();
}
public HashMap<String, String> getAttributes(){
attributes.put("first", "valueOfFirst");
attributes.put("second", "valueOfSecond");
attributes.put("third", "valueOfThird");
return attributes;
}
}
公共类演示{
公共静态void main(字符串[]args){
ConcreteBuilder=新的ConcreteBuilder();
混凝土=建筑商。加上(“第四”、“第四个值”)。建筑();
for(字符串值:concrete.getAttributes().values())
系统输出打印项次(值);
}
}
等级混凝土建造师{
私人混凝土;
公共混凝土建造商(){
混凝土=新混凝土();
}
具有(字符串键、字符串值)的公共混凝土生成器{
concrete.getAttributes().put(键,值);
归还这个;
}
公共混凝土建筑(){
返回混凝土;
}
}
等级混凝土{
私有HashMap属性;
公共混凝土(){
attributes=newhashmap();
}
公共HashMap getAttributes(){
属性。放置(“第一”、“第一值”);
属性。put(“second”、“valueOfSecond”);
出售(“第三”、“第三价值”);
返回属性;
}
}
这里的神奇之处在于,您(可能)不再需要所有这些子类。
如果这些子类的行为没有改变,而只是改变了它们的变量,那么使用这样的系统应该没问题。
我强烈建议你阅读Martin Fowler关于这个主题的文章,虽然有好的地方和不好的地方,但我认为这是一个好的地方
我希望这能让你更接近一个答案,祝你好运。:) 我知道这有点晚了,但我希望你能给我一个答案!当时我的主管告诉我要完全避免构建器模式,因为bean需要有getter和setter方法。我很天真,希望实现一个“聪明”的解决方案。
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder> {
private int calories = 0;
public Builder() {}
public T calories(int val) {
calories = val;
return (T) this;
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder<Builder> {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
public abstract BaseClass {
// various fields go here
...
public abstract Builder<T extends BaseClass, B extends Builder<T,B>> {
// add chaining methods here
...
public T build() {
if (isValid()) return new T(this);
else Throw new IllegalArgumentException("Invalid data passed to builder.");
}
}
public BaseClass(Builder builder) {
// set fields of baseclass here
}
}
class ParentBuilder{
public ConcreteParent build(){
ConcreteParent parent = new ConcreteParent();
parent.setFirst(1);
parent.setSecond(2);
parent.setThird(3);
return parent;
}
}
class ChildBuilder{
public ConcreteChild build(ParentBuilder parentBuilder){
ConcreteParent parent = parentBuilder.build();
ConcreteChild child = new ConcreteChild();
child.setFirst(parent.getFirst());
child.setSecond(parent.getSecond());
child.setThird(parent.getThird());
child.setFourth(4); //Child specific value
child.setFifth(5); //Child specific value
return child;
}
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
public class Demo {
public static void main(String[] args) {
ConcreteBuilder builder = new ConcreteBuilder();
Concrete concrete = builder.with("fourth", "valueOfFourth").build();
for(String value : concrete.getAttributes().values())
System.out.println(value);
}
}
class ConcreteBuilder{
private Concrete concrete;
public ConcreteBuilder(){
concrete = new Concrete();
}
public ConcreteBuilder with(String key, String value){
concrete.getAttributes().put(key, value);
return this;
}
public Concrete build(){
return concrete;
}
}
class Concrete{
private HashMap<String, String> attributes;
public Concrete(){
attributes = new HashMap<>();
}
public HashMap<String, String> getAttributes(){
attributes.put("first", "valueOfFirst");
attributes.put("second", "valueOfSecond");
attributes.put("third", "valueOfThird");
return attributes;
}
}