Java 设计问题:强制执行方法调用序列

2022-08-31 16:15:04

最近在一次采访中有人问我一个问题。

问题:有一个类用于分析代码的执行时间。该类是这样的:

Class StopWatch {

    long startTime;
    long stopTime;

    void start() {// set startTime}
    void stop() { // set stopTime}
    long getTime() {// return difference}

}

客户端应创建秒表的实例并相应地调用方法。用户代码可能会弄乱方法的使用,从而导致意外结果。Ex、start()、stop() 和 getTime() 调用应该按顺序排列。

必须“重新配置”此类,以便可以防止用户弄乱序列。

我建议在 start() 之前调用 stop() 时使用自定义异常,或者做一些 if/else 检查,但面试官不满意。

是否有处理此类情况的设计模式?

编辑:可以修改类成员和方法实现。


答案 1

首先,实现自己的Java分析器是浪费时间,因为可以使用好的Java分析器(也许这就是问题背后的意图)。

如果要在编译时强制执行正确的方法顺序,则必须使用链中的每个方法返回一些内容:

  1. start()必须返回 带有 stop 方法的 a。WatchStopper
  2. 然后必须返回带有该方法的 a。WatchStopper.stop()WatchResultgetResult()

当然,必须防止这些帮助程序类的外部构造以及访问其方法的其他方法。


答案 2

只需对接口进行微小的更改,您就可以使方法序列成为唯一可以调用的方法序列 - 即使在编译时也是如此!

public class Stopwatch {
    public static RunningStopwatch createRunning() {
        return new RunningStopwatch();
    }
}

public class RunningStopwatch {
    private final long startTime;

    RunningStopwatch() {
        startTime = System.nanoTime();
    }

    public FinishedStopwatch stop() {
        return new FinishedStopwatch(startTime);
    }
}

public class FinishedStopwatch {
    private final long elapsedTime;

    FinishedStopwatch(long startTime) {
        elapsedTime = System.nanoTime() - startTime;
    }

    public long getElapsedNanos() {
        return elapsedTime;
    }
}

用法很简单 - 每个方法都返回一个不同的类,该类仅具有当前适用的方法。基本上,秒表的状态被封装在类型系统中。


在评论中,有人指出,即使采用上述设计,您也可以呼叫两次。虽然我认为这是附加值,但从理论上讲,有可能把自己搞砸。然后,我能想到的唯一方法是这样的:stop()

class Stopwatch {
    public static Stopwatch createRunning() {
        return new Stopwatch();
    }

    private final long startTime;

    private Stopwatch() {
        startTime = System.nanoTime();
    }

    public long getElapsedNanos() {
        return System.nanoTime() - startTime;
    }
}

这与省略方法的分配不同,但这也是潜在的好设计。然后,一切都将取决于确切的要求...stop()