Implement a basic CachedWeatherForecaster proxy to cache all results of a WeatherForecaster.
Co-Authored-By: os222
This commit is contained in:
parent
68b7b9cf5f
commit
01f8d801b3
|
@ -0,0 +1,27 @@
|
|||
package ic.doc;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
// This class is a decorator for WeatherForecaster that caches all results.
|
||||
public class CachedWeatherForecaster implements WeatherForecaster {
|
||||
private final WeatherForecaster forecaster;
|
||||
private final HashMap<CacheKey, WeatherForecast> cache = new HashMap<>();
|
||||
|
||||
CachedWeatherForecaster(WeatherForecaster forecaster) {
|
||||
this.forecaster = forecaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherForecast forecastFor(WeatherRegion region, Weekday day) {
|
||||
CacheKey key = new CacheKey(region, day);
|
||||
WeatherForecast forecast = cache.get(key);
|
||||
if (forecast == null) {
|
||||
forecast = forecaster.forecastFor(region, day);
|
||||
cache.put(key, forecast);
|
||||
return forecast;
|
||||
}
|
||||
return forecast;
|
||||
}
|
||||
|
||||
private record CacheKey(WeatherRegion region, Weekday day) {}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package ic.doc;
|
||||
|
||||
public class CachedWeatherForecasterBuilder {
|
||||
private WeatherForecaster forecaster;
|
||||
|
||||
private CachedWeatherForecasterBuilder() {}
|
||||
|
||||
public static CachedWeatherForecasterBuilder cachedWeatherForecaster() {
|
||||
return new CachedWeatherForecasterBuilder();
|
||||
}
|
||||
|
||||
public CachedWeatherForecasterBuilder withForecaster(WeatherForecaster forecaster) {
|
||||
this.forecaster = forecaster;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CachedWeatherForecaster build() {
|
||||
return new CachedWeatherForecaster(forecaster);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package ic.doc;
|
||||
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.integration.junit4.JUnitRuleMockery;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static ic.doc.CachedWeatherForecasterBuilder.cachedWeatherForecaster;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
// Unit test for CachedWeatherForecaster decorator
|
||||
public class CachedWeatherForecasterTest {
|
||||
@Rule
|
||||
public JUnitRuleMockery context = new JUnitRuleMockery();
|
||||
|
||||
private final WeatherForecaster forecaster = context.mock(WeatherForecaster.class);
|
||||
private final CachedWeatherForecasterBuilder cachedWeatherForecaster =
|
||||
cachedWeatherForecaster().withForecaster(forecaster);
|
||||
|
||||
@Test
|
||||
public void forecastForInitialCall() {
|
||||
WeatherForecaster cachedForecaster = cachedWeatherForecaster.build();
|
||||
WeatherForecast expForecast = new WeatherForecast("Sunny", 20);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(forecaster).forecastFor(WeatherRegion.LONDON, Weekday.MONDAY);
|
||||
will(returnValue(expForecast));
|
||||
}});
|
||||
WeatherForecast actForecast = cachedForecaster.forecastFor(
|
||||
WeatherRegion.LONDON, Weekday.MONDAY
|
||||
);
|
||||
assertEquals(expForecast, actForecast);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forecastForCachedCall() {
|
||||
WeatherForecaster cachedForecaster = cachedWeatherForecaster.build();
|
||||
WeatherForecast expForecast = new WeatherForecast("Sunny Spells", 30);
|
||||
WeatherForecast badForecast = new WeatherForecast("Rainy", 10);
|
||||
context.checking(new Expectations() {{
|
||||
// Only one call, second must hit cache
|
||||
oneOf(forecaster).forecastFor(WeatherRegion.LONDON, Weekday.MONDAY);
|
||||
will(returnValue(expForecast));
|
||||
// Also make some other requests in-between
|
||||
oneOf(forecaster).forecastFor(WeatherRegion.LONDON, Weekday.TUESDAY);
|
||||
will(returnValue(badForecast));
|
||||
oneOf(forecaster).forecastFor(WeatherRegion.WALES, Weekday.MONDAY);
|
||||
will(returnValue(badForecast));
|
||||
}});
|
||||
cachedForecaster.forecastFor(WeatherRegion.LONDON, Weekday.MONDAY);
|
||||
cachedForecaster.forecastFor(WeatherRegion.LONDON, Weekday.TUESDAY);
|
||||
cachedForecaster.forecastFor(WeatherRegion.WALES, Weekday.MONDAY);
|
||||
WeatherForecast actForecast =
|
||||
cachedForecaster.forecastFor(WeatherRegion.LONDON, Weekday.MONDAY);
|
||||
assertEquals(expForecast, actForecast);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue