2

Consider the following implementation of a static factory pattern...

public class Names{
private static final Map<String, Name> NAME_MAP = new HashMap<>();
private final String firstName, lastName, strRep;


public static Name getInstance(String firstName, String lastName) throws IllegalArgumentException {
        /*
        Check parameters.
        */
        String firstName = firstName.toUpperCase();
        String lastName = lastName.toUpperCase();
        String strRep = firstName + " " + lastName;
        // "strRep" is a string concatenation which uses the first name and last name in conjunction.

        if (strRep.matches("^[A-Z]+ [A-Z]+$")) {
            strRep = firstName + " " + lastName;
            Name name = NAME_MAP.get(strRep);
            if (name == null) {
                name = new Name(firstName, lastName, strRep);
                NAME_MAP.put(strRep, name);
            }
            return name;
        } else {
            throw new IllegalArgumentException("The parameters entered are invalid.");
        }

    }

Consider the situation in our codebase we use a new Name object temporarily (say as a local variable). Since the map holds an object reference, it now seems we have to manually clean up that map. This is as opposed to relying on garbage collection to clean up unused object references (in regular constructors). Is there a preferred way of cleaning up all object references without a client using the factory having to do this manually?

9
  • Response to @Robert. So in Java objects are reference data-types which are cleaned up by the Java garbage collector once there are no more variables which reference that object. Since the map in the static factory constructor pattern holds references to that object the object once constructed is retained in memory. This is even if the probability of that object being returned again is so low the object might as well not exist (its just using up space in memory). – Callum Dempsey Leach May 12 '18 at 20:54
  • 1
    Use a WeakReference to store the object in the HashMap. See javacodegeeks.com/2012/01/… – Robert Harvey May 12 '18 at 20:54
  • I've never used a WeakReference before. Would you kindly be able to respond with a demonstration? – Callum Dempsey Leach May 12 '18 at 20:55
  • Read the article I linked. – Robert Harvey May 12 '18 at 20:56
  • 1
    Why are you storing them in the static map in the first place, then? – whatsisname May 12 '18 at 21:47
5

In your factory implementation you cache all name objects created, returning the same instance if a new name with the same first and last name string is requested.

When you create a cache like this you should ensure that it doesn't simply grow forever. You should limit the number of items it holds and remove old ones when you hit that limit.

Your problem isn't the garbage collection its the simplistic cache implementation.

For Example, you could add a DateLastAccessed and MaxObjects variable to the cache. when you hit MaxObjects remove the least used Name before adding a new one.

3
  • I was going to give you the tick but there is a further question I feel needs answering before you can. If implementing a DateLastAccessed and MaxObjects variable to the cache, then how are we supposed to tell the difference between an object which hasn't been accessed for a while (but its object reference is still being held), and an object which is being used. For instance, an object might be "last accessed" 24hrs ago, so we may think to clean it up, but the object may still be held by reference in memory by some other object or implementing client. – Callum Dempsey Leach May 13 '18 at 11:49
  • I'm imagining an updateInstance method in the static factory which has to be called everytime an object is accessed. Unless Java provides a default implementation for telling us when an object was last used? – Callum Dempsey Leach May 13 '18 at 11:50
  • 5
    you are conflating "object reference held" with "needs to be in the cache" let the garbage collector worry about object references, you worry about how many objects you want to hold in the cache and for how long – Ewan May 13 '18 at 11:55
2

You seem to be very evasive as to what your actual problem is, but you haven't shown a need to hold onto the Name instances at all. Just return a new Name each call, and let the GC sort it out. At which point you can just move this to the Name constructor

As an aside, you seem to be mutating your parameters to do your validation. Do you mean for all Names to be uppercase?

3
  • Names don't actually feature in any implementation. I'm reading books and not actually developing a program which does any of this (whilst I'm doing Java I'm not writing any factories at the moment). It's the nature of the question which I wanted to focus on. So I'm not being "evasive" as such (ducking and diving and not wanting to show anything), there's genuinely just not a situation where I need to do any of this right now. Sorry for the confusion - but if you must know I thought of this in the shower. – Callum Dempsey Leach May 16 '18 at 14:40
  • @CallumDempseyLeach it's very much a case of YAGNI. When you have a specific case, you have context to decide on an appropriate cache invalidation strategy. In the abstract, a cache is unnecessary – Caleth May 16 '18 at 15:20
  • Thanks for this, in a pragmatic context I think you're correct with this. I'm just not someone who uses forums as the de-facto answer to problem solving, I like to focus on understanding underlying concepts as much as I can and tackle problems on my own. So there was no underlying 'problem' to solve, though I respect that asking "when to invalidate a cache" is associated with practical use case. – Callum Dempsey Leach Mar 26 '19 at 13:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.