Java 基于状态的设计模式的名称是什么?

What is this the name of this Java state-based design pattern?

在我的工作中,我们有调查,一项调查涉及多个步骤。我从事自动化工作,因此我围绕为这些调查创建的页面对象设计测试。我们将此特定调查称为 "flow" 调查,因为它有多个步骤。因此,您可以跳过第 1 步(调查 A),然后完成或跳过第 2 步(调查 B),然后完成或跳过第 3 步(调查 C)。天真地,我们可以编写一个只包含如下方法的测试:

public void completeSurveyA() {
    //...
}
public void skipSurveyB() {
    //...
}
public void completeSurveyB() {
    //...
}
public void skipSurveyC() { 
    //...
}
public void completeSurveyC() {
    //...
}

你会像这样使用它

completeSurveyA();
skipSurveyB();
completeSurveyC();

然而,这可能是个问题,因为我们可能会在调用 completeSurveyA() 之前调用 completeSurveyB(),调用 completeSurveyA 两次,等等,这样测试就会中断。为避免这种情况,我引入了一种不同的方法,即在 surveyA 上调用方法将 return 一个 surveyB 对象,这将 return 一个 surveyC 对象。

public class SurveyFlow() {
    public SurveyB completeSurveyA() {
        //...
        return new SurveyB();
    }
    private class SurveyB() {
        public SurveyC skipSurveyB() {
            //...
            return new SurveyC();
        }
        public SurveyC completeSurveyB() {
            //...
            return new SurveyC();
        }
        private class SurveyC() {
            public void skipSurveyC() {
                //...
            }
            public void completeSurveyC() {
                //...
            }
        }
    }
}

你会像这样使用它

new SurveyFlow().completeSurveyA().skipSurveryB().completeSurveyC();

这个模式让我想起了状态机,因为在不同的状态下你只能使用某些方法,但我想知道这个模式是否有更具体的名称。

这在某种程度上是State模式,但并不完全遵循GoF所描述的State模式,因为你不是在改变单个对象的状态,而是创建并返回一个不同的新对象class 之后使用。

实际上,这更类似于构建器模式,其中 completeSurveyC() 充当 buildgetResult 方法,从指定的多个组成部分构建 Surway早些时候。

根据您的示例的 类,它是 FluentInterface:

Probably the most important thing to notice about this style is that the intent is to do something along the lines of an internal DomainSpecificLanguage. (...) The API is primarily designed to be readable and to flow.

这不是构建器模式,因为您没有构建任何东西(即您没有最终的 build() 方法,其中在前面的步骤中收集的数据用于创建实例)。

这也不是状态模式,因为操作(在本例中为 skip()complete())不依赖于对象的状态(实际上步骤没有状态)。

会是状态模式,如果整个调查被建模为具有一种方法的对象,其实现取决于不同的状态(在这种情况下,状态将是步骤加上采取的行动,即 surveyACompletedsurveyASkippedsurveyBCompletedsurveyBSkipped 等,而方法类似于 nextStep()):

public class SurveyFlow {

    private SurveyState state; // this represents the current step

    public SurveyFlow(boolean skipFirst) {
        this.state = skipFirst ? new SurveyASkipped() : new SurveyACompleted();
    }

    void setState(SurveyState state) {
        this.state = state;
    }

    public void takeStep(boolean skipNext) { // takeStep operation delegated 
                                             // to the state (current step)
        this.state.takeStep(skipNext, this); // "this" passed to the step so 
                                             // that it can switch to the 
                                             // next step if needed
    }
}

状态将由 SurveyFlow 的每个步骤多态表示:

abstract class SurveyState {

    protected abstract void takeStep(boolean skipNext, SurveyFlow survey);
}

调查 A 状态如下:

class SurveyACompleted extends SurveyState {

    protected void takeStep(boolean skipNext, SurveyFlow survey) {
        // ...

        survey.setState(skipNext ? new SurveyBSkipped() : new SurveyBCompleted());
    }
}

class SurveyASkipped extends SurveyState {

    protected void takeStep(boolean skipNext, SurveyFlow survey) {
        // ...

        survey.setState(skipNext ? new SurveyBSkipped() : new SurveyBCompleted());
    }
}

调查 B 状态如下:

class SurveyBCompleted extends SurveyState {

    protected void takeStep(boolean skipNext, SurveyFlow survey) {
        // ...

        survey.setState(skipNext ? new SurveyCSkipped() : new SurveyCCompleted());
    }
}

class SurveyBSkipped extends SurveyState {

    protected void takeStep(boolean skipNext, SurveyFlow survey) {
        // ...

        survey.setState(skipNext ? new SurveyCSkipped() : new SurveyCCompleted());
    }
}

以你的例子为例:

  1. 完成调查 A
  2. 跳过调查 B
  3. 完成调查 C

你可以这样做:

SurveyFlow survey = new SurveyFlow(false); // will complete survey A
survey.takeStep(true);                     // completed survey A and will skip survey B
survey.takeStep(false);                    // skipped survey A and will complete survey C
survey.takeStep(true);                     // completed survey C

如果调查 C 是最后一步,那么它可以忽略 boolean 参数并且不应设置进一步的步骤。