Once given more thought
In hindsight it sounds like they were looking for the execute around pattern. They're usually used to do things like enforce closing of streams. This is also more relevant due to this line:
Is there a design pattern to handle these kind of situations?
The idea is you give the thing that does the "executing around" some class to do somethings with. You'll probably use Runnable
but it's not necessary. Runnable
makes the most sense and you'll see why soon. In your StopWatch
class add some method like this
public long measureAction(Runnable r) {
start();
r.run();
stop();
return getTime();
}
You would thing call it like this
StopWatch stopWatch = new StopWatch();
Runnable r = new Runnable() {
// Put some tasks here you want to measure.
};
long time = stopWatch.measureAction(r);
This makes it fool proof. You don't have to worry about handling stop before start or people forgetting to call one and not the other, etc. The reason Runnable
is nice is because
- Standard java class, not your own or third party
- End users can put whatever they need in the
Runnable
to be done.
(If you were using it to enforce stream closing then you could put the actions that need to be done with a database connection inside so the end user doesn't need to worry about how to open and close it and you simultaneously force them to close it properly.)
If you wanted, you could make some StopWatchWrapper
instead leave StopWatch
unmodified. You could also make measureAction(Runnable)
not return a time and make getTime()
public instead.
The Java 8 way to calling it is even simpler
StopWatch stopWatch = new StopWatch();
long time = stopWatch.measureAction(() - > {/* Measure stuff here */});
Original answer
More hindsight edit: OP mentions in a comment,
"The three methods should remain intact and are only interface to the programmer. The class members and method implementation can change."
So the below is wrong because it removes something from the interface. (Technically, you could implement it as an empty method but that seems to be like a dumb thing to do and too confusing.) I kind of like this answer if the restriction wasn't there and it does seem to be another "fool proof" way to do it so I will leave it.
To me something like this seems to be good.
class StopWatch {
private final long startTime;
public StopWatch() {
startTime = ...
}
public long stop() {
currentTime = ...
return currentTime - startTime;
}
}
The reason I believe this to be good is the recording is during object creation so it can't be forgotten or done out of order (can't call stop()
method if it doesn't exist).
One flaw is probably the naming of stop()
. At first I thought maybe lap()
but that usually implies a restarting or some sort (or at least recording since last lap/start). Perhaps read()
would be better? This mimics the action of looking at the time on a stop watch. I chose stop()
to keep it similar to the original class.
The only thing I'm not 100% sure about is how to get the time. To be honest that seems to be a more minor detail. As long as both ...
in the above code obtain current time the same way it should be fine.
StoppedStopWatch
withstart()
method that returns aRunningStopWatch
with astop()
method. (And then prevent any direct use of the underlyingStopWatch
, for instance by making it package private.) – aioobe 22 hours ago