Java 在调用任何函数之前,如何在fluent API中传递参数?

Java 在调用任何函数之前,如何在fluent API中传递参数?,java,Java,我有这样的课 public class AImpl implements A { private String variable = "init"; @Override public A choice(A... choices) { return this; } @Override public A execute() { variable = "execute"; return this;

我有这样的课

public class AImpl implements A {
    private String variable = "init";

    @Override
    public A choice(A... choices) {
        return this;
    }

    @Override
    public A execute() {
        variable = "execute";
        return this;
    }
}
我可以这样使用它(简单的例子)

或者像这样(更复杂的示例,具有可变的期望值)

我正在努力实现的目标

每次有选择时,我都希望将
变量的最后一个值
传播到每个新实例。这是一个复杂示例的图形版本,在这里我包围了我所称的传播

我的问题是什么

在调用任何其他函数之前(在上面的简单示例中调用
execute
之前,因为此函数使用(并且可以修改)此变量),如何将此
变量
传播到
选项
列表中的所有对象

我尝试过的

  • 我不能使用构造函数,因为我没有对变量的引用

    public AImpl(String variable) {
        this.variable = variable;
    }
    
  • 此代码将不起作用,因为变量将在所有函数之后设置

    @Override
    public A choice(A... choices) {
        for(A a : choices) {
            a.setVariable(variable);
        }
    }
    
  • 我尝试使用
    Builder
    (例如,设置所有值,并仅在末尾创建实例,例如从选择函数)。但是将函数
    execute
    choice
    …execute().execute().choice()…
    )链接起来是有意义的。因此,建筑商变得很难创建,而且可能变得非常大

  • 我还尝试将变量移动到
    上下文
    类中,但如果在
    选项
    中我有另一个选择(在更复杂的示例中),则该变量不起作用。这是我当前的上下文类

    public class Context {
        private static Context instance = null;
        private String variable;
    
        private Context(){};
    
        public String getVariable() {
            return variable;
        }
    
        public void setVariable(String variable) {
            this.variable = variable;
        }
    
        public static void set(String variable) {
            if(Context.instance == null)
                Context.instance = new Context();
            Context.instance.setVariable(variable);
        }
    
        public static String get() {
            if(Context.instance == null)
                throw new NullPointerException();
            return Context.instance.getVariable();
        }
    }
    

问题在于,新的AImpl实例需要继承其“父”AImple实例的上下文,即调用
choice()
的实例。您不能使用
new
操作符执行此操作。相反,您应该有一个使用继承的
变量创建实例的方法

public A[] createChoices(int count, A optionalDefaultValues...) {
    // return an array of clones of itself (possibly with adjusted defaults)
}

我终于找到了一个基于
Context
方法的有效解决方案(参见我的尝试?)

主要思想

有两个主要观点。第一种方法是将单个变量(在上下文对象内部)替换为一个
堆栈

Stack<String> variables = new Stack<>();
第二个主要思想是每次创建新选项时复制堆栈顶部的值,并在每个选项结束时将其删除

我的代码

这是我的代码,如果它能帮助其他人。我肯定有很多事情要做,以改善它,但它解决了我原来的问题

  • TestSo.java

    public class TestSo {
        @Test
        public void testSo() {
            AImpl.create().choice(
                    new ChoiceList()
                            .add(AChoice.create().execute())
                            .add(AChoice.create().choice(
                                    new ChoiceList().add(AChoice.create())
                            ))
                            .add(AChoice.create().execute().choice(
                                    new ChoiceList()
                                            .add(AChoice.create())
                                            .add(AChoice.create())
                            ))
            );
        }
    }
    
  • A.java

    public interface A {
        A choice(ChoiceList choices);
        A execute();
    }
    
  • AAbstract.java

    public class AAbstract implements A {
        @Override
        public A choice(ChoiceList choices) {
            return this;
        }
    
        @Override
        public A execute() {
            String variable = Context.get();
    
            //...
    
            Context.set("execute");
            return this;
        }
    }
    
  • AImpl.java

    public class AImpl extends AAbstract {
        private AImpl() {
            Context.set("init");
        }
    
        public static AImpl create() {
            return new AImpl();
        }
    }
    
  • java

    public class AChoice extends AAbstract {
        private AChoice() {
            Context.duplicate();
        }
    
        public static AChoice create() {
            return new AChoice();
        }
    
        @Override
        public AChoice choice(ChoiceList choices) {
            super.choice(choices);
            return this;
        }
    
        @Override
        public AChoice execute() {
            super.execute();
            return this;
        }
    }
    
  • ChoiceList.java

    public class ChoiceList {
        private List<AChoice> choices = new ArrayList<>();
    
        public ChoiceList add(AChoice choice) {
            Context.remove();
            choices.add(choice);
            return this;
        }
    }
    
    公共类选秀员{
    私有列表选项=新建ArrayList();
    公共唱诗班成员增补(阿乔伊斯选择){
    Context.remove();
    选择。添加(选择);
    归还这个;
    }
    }
    
  • Context.java

    public class Context {
        private static Context instance = null;
        private Stack<String> variables = new Stack<>();
    
        private Context(){};
        public String peek() {return variables.peek();}
        public String pop() {return variables.pop();}
        public void fork() {variables.push(variables.peek());}
        public void push(String variable) {variables.push(variable);}
    
        public static void set(String variable) {
            if(Context.instance == null)
                Context.instance = new Context();
            Context.instance.push(variable);
        }
    
        public static String get() {
            if(Context.instance == null)
                throw new NullPointerException();
            return Context.instance.pop();
        }
    
       public static void remove() {
            if(Context.instance == null)
                throw new NullPointerException();
            Context.instance.pop();
        }
    
        public static void duplicate() {
            if(Context.instance == null)
                throw new NullPointerException();
            Context.instance.fork();
        }
    
        public static String read() {
            if(Context.instance == null)
                throw new NullPointerException();
            return Context.instance.peek();
        }
    }
    
    公共类上下文{
    私有静态上下文实例=null;
    私有堆栈变量=新堆栈();
    私有上下文(){};
    公共字符串peek(){return variables.peek();}
    公共字符串pop(){return variables.pop();}
    public void fork(){variables.push(variables.peek());}
    public void push(字符串变量){variables.push(变量);}
    公共静态无效集(字符串变量){
    if(Context.instance==null)
    Context.instance=新上下文();
    Context.instance.push(变量);
    }
    公共静态字符串get(){
    if(Context.instance==null)
    抛出新的NullPointerException();
    返回Context.instance.pop();
    }
    公共静态void remove(){
    if(Context.instance==null)
    抛出新的NullPointerException();
    Context.instance.pop();
    }
    公共静态无效副本(){
    if(Context.instance==null)
    抛出新的NullPointerException();
    Context.instance.fork();
    }
    公共静态字符串读取(){
    if(Context.instance==null)
    抛出新的NullPointerException();
    返回Context.instance.peek();
    }
    }
    

您的问题不是很清楚……我认为您需要某种构建器对象来构造您所需的所有数据的表示形式,并且只在最后构建器构造真实的对象。好的,我将尝试重新构建我关于
builder
的问题。当你说
new AImpl[new AImpl()]
你的意思是
new AImpl[]{new AImpl()}
?什么是
count
?欲望清单的大小?我想应该是清单的大小。但是,如果你想把它作为一个论点来传递,那就取决于你了。也许您只需在varargs列表中将“new”A对象作为原型传递,并创建相同数量的对象。
public class AChoice extends AAbstract {
    private AChoice() {
        Context.duplicate();
    }

    public static AChoice create() {
        return new AChoice();
    }

    @Override
    public AChoice choice(ChoiceList choices) {
        super.choice(choices);
        return this;
    }

    @Override
    public AChoice execute() {
        super.execute();
        return this;
    }
}
public class ChoiceList {
    private List<AChoice> choices = new ArrayList<>();

    public ChoiceList add(AChoice choice) {
        Context.remove();
        choices.add(choice);
        return this;
    }
}
public class Context {
    private static Context instance = null;
    private Stack<String> variables = new Stack<>();

    private Context(){};
    public String peek() {return variables.peek();}
    public String pop() {return variables.pop();}
    public void fork() {variables.push(variables.peek());}
    public void push(String variable) {variables.push(variable);}

    public static void set(String variable) {
        if(Context.instance == null)
            Context.instance = new Context();
        Context.instance.push(variable);
    }

    public static String get() {
        if(Context.instance == null)
            throw new NullPointerException();
        return Context.instance.pop();
    }

   public static void remove() {
        if(Context.instance == null)
            throw new NullPointerException();
        Context.instance.pop();
    }

    public static void duplicate() {
        if(Context.instance == null)
            throw new NullPointerException();
        Context.instance.fork();
    }

    public static String read() {
        if(Context.instance == null)
            throw new NullPointerException();
        return Context.instance.peek();
    }
}