Recap from last time
Designed interface
Duration
Implemented it as class
DurationImpl
But used a silly representation:
private final int hours; private final int minutes; private final int seconds;
What we'd like to do now
Use a less-silly representation:
private final long inSeconds;
What are our options?
We made one bad decision
But we also made two good decisions:
Information hiding (can change representation because fields are
private
)Interface polymorphism (code that uses the
Duration
interface will work with future implementations of it)
Let's explore the latter
Code time
DurationImpl
:
public Duration plus(Duration d) {
return new DurationImpl(inSeconds() + d.inSeconds());
}
CompactDuration
:
public Duration plus(Duration that) {
return new CompactDuration(inSeconds() + d.inSeconds());
}
AbstractDuration
:
public Duration plus(Duration d) {
return new ❓❓❓(inSeconds() + d.inSeconds());
}
A design pattern
Problem
Superclass doesn't know what class to construct, but subclasses do
Solution
Factory method pattern, in which the superclass
defers object construction to subclasses
by declaring an abstract factory method
that subclasses must implement.
DurationImpl
:
public Duration plus(Duration d) {
return new DurationImpl(inSeconds() + d.inSeconds());
}
CompactDuration
:
public Duration plus(Duration that) {
return new CompactDuration(inSeconds() + d.inSeconds());
}
AbstractDuration
:
public Duration plus(Duration d) {
return fromSeconds(inSeconds() + d.inSeconds());
}
DurationImpl
:
public Duration plus(Duration d) {
return new DurationImpl(inSeconds() + d.inSeconds());
}
CompactDuration
:
public Duration plus(Duration that) {
return new CompactDuration(inSeconds() + d.inSeconds());
}
AbstractDuration
:
public Duration plus(Duration d) {
return fromSeconds(inSeconds() + d.inSeconds());
}
protected abstract Duration fromSeconds(long);
DurationImpl
:
public Duration fromSeconds(long s) {
return new DurationImpl(s);
}
CompactDuration
:
public Duration plus(Duration that) {
return new CompactDuration(inSeconds() + d.inSeconds());
}
AbstractDuration
:
public Duration plus(Duration d) {
return fromSeconds(inSeconds() + d.inSeconds());
}
protected abstract Duration fromSeconds(long);
DurationImpl
:
public Duration fromSeconds(long s) {
return new DurationImpl(s);
}
CompactDuration
:
public Duration fromSeconds(long s) {
return new CompactDuration(s);
}
AbstractDuration
:
public Duration plus(Duration d) {
return fromSeconds(inSeconds() + d.inSeconds());
}
protected abstract Duration fromSeconds(long);