Java – a good pattern for combined caching and reinitialization

Architecturedesign-patternsjavalazy-initializationmethods

I have a situation where I have three requirements:

  1. Lazy initialization – don't create the collection until asked for it
  2. Caching – keep the collection in memory on the object
  3. Reinitialization – be able to reinitialize the collection when desired, instead of simply getting the existing results.

This is simply an optimization inside a single class – it is not loading anything from a database and ideally I'd like just a good method design pattern for this, not a multiple-class design.

Usually for lazy initialization I'd have this:

Collection getCollection() {
    if (collection != null) {
         // generate and set collection
    }
    return collection;
}

But now I'm having trouble deciding on the best way to provide for reinitialization of a fresh collection and getting that collection. A fresh boolean parameter would work, but adding a parameter to a getter doesn't seem to feel right (maybe that's the Java in me talking — I could be convinced).

Best Answer

If you're limiting yourself to a single method call then I can't honestly imagine a parameterless solution that distinguishes between retrieving the cached value and a reinitialized value.

Every cache I've seen uses one of the following patterns:

  • An Invalidate or Expire method that flags the value for reinitialization on the next lookup;

  • A boolean or enumeration parameter, such as the one you've ruled out;

  • A separate reinitialization method, i.e. getNewCollection.

I do think it must be the Java in you talking, because in other languages I'm very much accustomed to passing parameters in cache lookups - in some cases one of the parameters may even be an anonymous method or function pointer telling the cache how to get the value.

When designing a cache based on deferred initialization, you'll almost certainly also want to have method overloads that take parameters for priority and/or expiration, since there's no longer any Put or Store method to hold them. So, I think the notion of a parameterless lazy-loaded lookup method with optional refresh is pretty much out the window.

If you're uncomfortable with it being a getter, then just give it a different name like Load or Lookup.

P.S. I realize you may not actually be designing a cache here, but the principles still apply; you don't want to have something that acts like a cache internally but doesn't provide cache semantics. That would just lead to headaches.