Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:处理状态和继承的设计模式_Java_Design Patterns - Fatal编程技术网

Java:处理状态和继承的设计模式

Java:处理状态和继承的设计模式,java,design-patterns,Java,Design Patterns,我会尽力解释我在汽车方面的问题。我有AbstractCar,我的库的用户(开发人员)将创建他们的许多具体汽车。这辆车有状态,这种状态对图书馆的正常工作非常重要!只有汽车可以控制其状态(没有任何驾驶员等)。方法的状态在方法开始和结束时开始/停止。此外,所有车辆必须实现接口车辆 public enum State{ STARTING, STARTED, STOPPING, STOPPED } public interface Car{ public void start(); p

我会尽力解释我在汽车方面的问题。我有AbstractCar,我的库的用户(开发人员)将创建他们的许多具体汽车。这辆车有状态,这种状态对图书馆的正常工作非常重要!只有汽车可以控制其状态(没有任何驾驶员等)。方法的状态在方法开始和结束时开始/停止。此外,所有车辆必须实现接口车辆

public enum State{
   STARTING, STARTED, STOPPING, STOPPED
}

public interface Car{
   public void start();
   public void stop();
   public State getState();
}
我尝试了两种变体

变体1

public abstract class AbstractCar implements Car{
  private State state;
  public void setState(State state){...}
  public State getState(){...}
}

public class ConcreteCar extends AbstractCar{
  @Override
  public void start(){
     setState(stateK);
     ...
     setState(stateN);
  }

  @Override
  public void stop(){
     setState(stateR);
     ...
     setState(stateO);
  }
}
在变体1中,库的用户必须记住更改状态。如果他忘记做这件事,那么代码中就会有一个bug

变体2

public abstract class AbstractCar implements Car{
  private State state;
  protected void doOnStart(){ }
  protected void doOnStop(){ }
  public final void start(){
    state=...;
    doOnStart();
    state=...;
  }
  public final void stop(){
    state=...;
    doOnStop();
    state=...;
  }
}

public class ConcreteCar extends AbstractCar{
  @Override
  protected void doOnStart(){
    ....
  }

  @Override
  protected void doOnStop(){
     ...
  }
}
在变体2中,用户不能忘记状态,因为它已经超出了他的控制范围,但是如果我有许多状态和方法可以更改,这不是一个很好的方法


有人能为解决这类问题提供任何模式或技术建议吗?

使用状态设计模式

将您的AbstractCar作为上下文,并使用它来管理汽车的状态

我做了一个如下的例子。希望我理解正确

public interface IState {
    public void changeState(Car inContext);

    public void doSomething();
}

public interface Car {
    enum CarState{
        start,
        stop,
        auto
    }

    public void setState(CarState state);
}

public class AbstractCar implements Car {
    IState m_currentState;

    IState startState = new StartState();
    IState stopState = new StopState();
    IState autoState = new AutoNavigateState();

    public AbstractCar() {
        m_currentState = stopState;
    }

    public void start() {
        setState(CarState.start);
        m_currentState.doSomething();
        m_currentState.changeState(this);
    }

    public void stop() {
        setState(CarState.stop);
        m_currentState.doSomething();
        m_currentState.changeState(this);
    }

    public void autoNavigate() {
        setState(CarState.auto);
        m_currentState.doSomething();
        m_currentState.changeState(this);
    }

    public void setState(CarState state) {
        if (state == CarState.start) {
            m_currentState = startState;
        } else if (state == CarState.stop) {
            m_currentState = stopState;
        } else {
            m_currentState = autoState;
        }
    }

}

public class StartState implements IState {

    @Override
    public void changeState(Car car) {
        car.setState(CarState.stop);
    }

    @Override
    public void doSomething() {
        // TODO Auto-generated method stub

    }

}

public class StopState implements IState{

    @Override
    public void changeState(Car car) {
        car.setState(CarState.start);
    }

    @Override
    public void doSomething() {
        // TODO Auto-generated method stub

    }

}

public class AutoNavigateState implements IState{

    @Override
    public void changeState(Car inContext) {
        // TODO Auto-generated method stub

    }

    @Override
    public void doSomething() {
        // TODO Auto-generated method stub

    }

}
在变体2中,用户不能忘记状态,因为它已经存在 在他的控制之外

这是可取的吗

public abstract class AbstractCar implements Car{
   ...
  public final void start(){
    state=...;
    doOnStart();
    state=...;
  }
  ...
}
在抽象类中,您为具体类确定它们应该被使用的状态。
对于具体类来说,这似乎不是一个非常灵活的解决方案,因为状态更改应该取决于start()方法中可能更改的上下文。

您应该在AbstractCar中使用AbstractMethod来允许和强制具体类选择如何定义它们的状态,例如:

假设这个具体类:

public abstract class AbstractCar implements Car{
   ...
  public abstract State getStateBeforeStart();
  public abstract State getStateAfterStart();
  ...
  public final void start(){
    state = getStateBeforeStart();
    doOnStart();
    state = getStateAfterStart();
  }
  ...
}

您还可以使用Javadoc正确地记录类的API和具体类的职责,以便更好地使用它。

如果您想完全控制汽车在给定时刻的状态以及允许的转换,第二种方法是使用的基本模式

您可以修改调用子类代码的方式(无论是通过调用抽象方法还是其他类型的回调),但基本模式将是相同的-您的
AbstractCar
的代码将包含状态和转换的逻辑,定义了可以调用“外部”代码的点。这些有时也被称为“挂钩”

这种方法的一个(可能有点牵强)示例是,请求通过一个复杂的工作流,在某些给定阶段(例如验证)可以执行用户提供的代码,但无法直接设置请求的状态

如果您想让您的用户(即子类作者)能够影响汽车的状态,您可以通过接受回调的返回值(影响以下状态转换),或者在某些情况下,只需进行适当的错误处理,以可控的方式进行操作:

public final void start(){
    state=STARTING;
    try {
        doOnStart();
        state=STARTED;
    } catch (RuntimeException e) {
        // handle error
        state=STOPPED;
    }
}

变体2是模板方法模式:@cricket_007我刚刚读过关于状态模式的文章,我正确地理解它,它允许汽车根据状态改变行为。但我不需要不同的行为。我只需要控制国家,当然。从你的psudoCode中,似乎你有一些类似于开始、开始、停止和停止的状态?@cricket_007是的,你是对的。如果你能举一个外部代码的例子,说明这些状态是如何重要,也许你会得到一个更好的答案