Skip to content

Commit

Permalink
Define and use singletons instead of new stateless instances for each
Browse files Browse the repository at this point in the history
call

The following now define singletons:
- org.apache.hc.core5.http.impl.routing.UriPathRouter.BestMatcher
- org.apache.hc.core5.http.impl.routing.UriPathRouter.OrderedMatcher
- org.apache.hc.core5.http.impl.routing.UriPathRouter.RegexMatcher
  • Loading branch information
garydgregory committed Oct 29, 2024
1 parent e33ad8a commit 7e507b6
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ public String toString() {
}

static <T> UriPathRouter<?, T> bestMatch(final List<PathRoute<String, T>> routes) {
return new UriPathRouter<>(Function.identity(), new BestMatcher<>(), routes);
return new UriPathRouter<>(Function.identity(), BestMatcher.getInstance(), routes);
}

static <T> UriPathRouter<?, T> ordered(final List<PathRoute<String, T>> routes) {
return new UriPathRouter<>(Function.identity(), new OrderedMatcher<>(), routes);
return new UriPathRouter<>(Function.identity(), OrderedMatcher.getInstance(), routes);
}

static <T> UriPathRouter<?, T> regEx(final List<PathRoute<String, T>> routes) {
return new UriPathRouter<>(Pattern::compile, new RegexMatcher<>(), routes);
return new UriPathRouter<>(Pattern::compile, RegexMatcher.getInstance(), routes);
}

private static final PathPatternMatcher PATH_PATTERN_MATCHER = PathPatternMatcher.INSTANCE;
Expand All @@ -83,9 +83,24 @@ static <T> UriPathRouter<?, T> regEx(final List<PathRoute<String, T>> routes) {
* <li>{@code *<uri-path>}</li>
* <li>{@code <uri-path>*}</li>
* </ul>
* <p>
* This class has no instance state.
* </p>
*/
final static class BestMatcher<T> implements BiFunction<String, List<PathRoute<String, T>>, T> {

@SuppressWarnings("rawtypes") // raw by design
private static final BestMatcher INSTANCE = new BestMatcher();

@SuppressWarnings({ "cast", "unchecked" }) // cast to call site
static <T> BestMatcher<T> getInstance() {
return (BestMatcher<T>) INSTANCE;
}

private BestMatcher() {
// singleton instance only
}

@Override
public T apply(final String path, final List<PathRoute<String, T>> routes) {
PathRoute<String, T> bestMatch = null;
Expand Down Expand Up @@ -115,9 +130,24 @@ public T apply(final String path, final List<PathRoute<String, T>> routes) {
* <li>{@code *<uri-path>}</li>
* <li>{@code <uri-path>*}</li>
* </ul>
* <p>
* This class has no instance state.
* </p>
*/
final static class OrderedMatcher<T> implements BiFunction<String, List<PathRoute<String, T>>, T> {

@SuppressWarnings("rawtypes") // raw by design
private static final OrderedMatcher INSTANCE = new OrderedMatcher();

@SuppressWarnings({ "cast", "unchecked" }) // cast to call site
static <T> OrderedMatcher<T> getInstance() {
return (OrderedMatcher<T>) INSTANCE;
}

private OrderedMatcher() {
// singleton instance only
}

@Override
public T apply(final String path, final List<PathRoute<String, T>> routes) {
for (final PathRoute<String, T> route : routes) {
Expand All @@ -135,9 +165,24 @@ public T apply(final String path, final List<PathRoute<String, T>> routes) {

/**
* Finds a match for the given path from a collection of regular expressions.
* <p>
* This class has no instance state.
* </p>
*/
final static class RegexMatcher<T> implements BiFunction<String, List<PathRoute<Pattern, T>>, T> {

@SuppressWarnings("rawtypes") // raw by design
private static final RegexMatcher INSTANCE = new RegexMatcher();

@SuppressWarnings({ "cast", "unchecked" }) // cast to call site
static <T> RegexMatcher<T> getInstance() {
return (RegexMatcher<T>) INSTANCE;
}

private RegexMatcher() {
// singleton instance only
}

@Override
public T apply(final String path, final List<PathRoute<Pattern, T>> routes) {
for (final PathRoute<Pattern, T> route : routes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class TestUriPathRouter {

@Test
void testBestMatchWildCardMatching() {
final UriPathRouter.BestMatcher<Long> matcher = new UriPathRouter.BestMatcher<>();
final UriPathRouter.BestMatcher<Long> matcher = UriPathRouter.BestMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("*", 0L),
new PathRoute<>("/one/*", 1L),
Expand All @@ -58,7 +58,7 @@ void testBestMatchWildCardMatching() {

@Test
void testBestMatchWildCardMatchingSuffixPrefixPrecedence() {
final UriPathRouter.BestMatcher<Long> matcher = new UriPathRouter.BestMatcher<>();
final UriPathRouter.BestMatcher<Long> matcher = UriPathRouter.BestMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("/ma*", 1L),
new PathRoute<>("*tch", 2L));
Expand All @@ -67,7 +67,7 @@ void testBestMatchWildCardMatchingSuffixPrefixPrecedence() {

@Test
void testBestMatchWildCardMatchingExactMatch() {
final UriPathRouter.BestMatcher<Long> matcher = new UriPathRouter.BestMatcher<>();
final UriPathRouter.BestMatcher<Long> matcher = UriPathRouter.BestMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("exact", 1L),
new PathRoute<>("*", 0L));
Expand All @@ -76,7 +76,7 @@ void testBestMatchWildCardMatchingExactMatch() {

@Test
void testBestMatchWildCardMatchingNoMatch() {
final UriPathRouter.BestMatcher<Long> matcher = new UriPathRouter.BestMatcher<>();
final UriPathRouter.BestMatcher<Long> matcher = UriPathRouter.BestMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("/this/*", 1L),
new PathRoute<>("/that/*", 2L));
Expand All @@ -85,7 +85,7 @@ void testBestMatchWildCardMatchingNoMatch() {

@Test
void testOrderedWildCardMatching1() {
final UriPathRouter.OrderedMatcher<Long> matcher = new UriPathRouter.OrderedMatcher<>();
final UriPathRouter.OrderedMatcher<Long> matcher = UriPathRouter.OrderedMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("*", 0L),
new PathRoute<>("/one/*", 1L),
Expand Down Expand Up @@ -121,7 +121,7 @@ void testOrderedWildCardMatching1() {

@Test
void testOrderedWildCardMatchingSuffixPrefixPrecedence() {
final UriPathRouter.OrderedMatcher<Long> matcher = new UriPathRouter.OrderedMatcher<>();
final UriPathRouter.OrderedMatcher<Long> matcher = UriPathRouter.OrderedMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("/ma*", 1L),
new PathRoute<>("*tch", 2L));
Expand All @@ -130,7 +130,7 @@ void testOrderedWildCardMatchingSuffixPrefixPrecedence() {

@Test
void testOrderedStarAndExact() {
final UriPathRouter.OrderedMatcher<Long> matcher = new UriPathRouter.OrderedMatcher<>();
final UriPathRouter.OrderedMatcher<Long> matcher = UriPathRouter.OrderedMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("*", 0L),
new PathRoute<>("exact", 1L));
Expand All @@ -139,7 +139,7 @@ void testOrderedStarAndExact() {

@Test
void testOrderedExactAndStar() {
final UriPathRouter.OrderedMatcher<Long> matcher = new UriPathRouter.OrderedMatcher<>();
final UriPathRouter.OrderedMatcher<Long> matcher = UriPathRouter.OrderedMatcher.getInstance();
final List<PathRoute<String, Long>> routes = Arrays.asList(
new PathRoute<>("exact", 1L),
new PathRoute<>("*", 0L));
Expand All @@ -148,7 +148,7 @@ void testOrderedExactAndStar() {

@Test
void testRegExMatching() {
final UriPathRouter.RegexMatcher<Long> matcher = new UriPathRouter.RegexMatcher<>();
final UriPathRouter.RegexMatcher<Long> matcher = UriPathRouter.RegexMatcher.getInstance();
final List<PathRoute<Pattern, Long>> routes = Arrays.asList(
new PathRoute<>(Pattern.compile("/one/two/three/.*"), 3L),
new PathRoute<>(Pattern.compile("/one/two/.*"), 2L),
Expand All @@ -167,7 +167,7 @@ void testRegExMatching() {

@Test
void testRegExWildCardMatchingSuffixPrefixPrecedence() {
final UriPathRouter.RegexMatcher<Long> matcher = new UriPathRouter.RegexMatcher<>();
final UriPathRouter.RegexMatcher<Long> matcher = UriPathRouter.RegexMatcher.getInstance();
final List<PathRoute<Pattern, Long>> routes = Arrays.asList(
new PathRoute<>(Pattern.compile("/ma.*"), 1L),
new PathRoute<>(Pattern.compile(".*tch"), 2L));
Expand Down

0 comments on commit 7e507b6

Please sign in to comment.