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

标签 java design-patterns

我会尝试解释我在汽车上的问题。我有 AbstractCar,我的库的用户(开发人员)将创建许多他们的 ConcreteCar。这个 AbstractCar 有状态,这个状态对于库的正确工作非常重要!只有汽车可以控制它的状态(没有任何司机等)。方法中的状态更改在方法开始和结束时开始/停止。此外,所有汽车都必须实现汽车接口(interface)。

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 中,库的用户必须记住更改状态。如果他忘记这样做,那么代码中就会出现错误。

变体 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' s代码将包含状态和转换的逻辑,以及可以调用“外部”代码的定义点。这些有时也称为“ Hook ”。

这种方法的一个(可能有点牵强)例子是 JSF life-cycle请求经过复杂的工作流程,在某些给定阶段(例如验证),用户提供的代码可能会被执行 - 但它无法直接设置请求的状态。

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

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

关于Java:处理状态和继承的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41764780/

相关文章:

java - 作文课;使用 super 还是子?

java - 从 Tomcat 7 迁移到 Tomcat 9 后的 "Too many open files"

Java 无法为对象堆错误保留足够的空间

Android: fragment 之间跳转的正确方式

python - 互斥关键字参数的优雅模式?

parsing - 使用scala的日志解析策略

javascript - 这种寄生遗传模式好不好?

java - 将存储库包含在存储库 github 中

java - 左右对象在运行时或编译时评估/解决?

java - <children> 标签在 fxml 中有用吗?它应该被删除吗?