Search code examples
javaenumssingletonfactory-pattern

How do I return a limited number of cached instances in Java?


I have a "configuration" class that becomes a field of several other classes. It indicates some kind of configuration or "abilities" of those other classes to allow or disallow actions. The configuration class as of now contains a set of four independent booleans and will likely remain like that --or grow with another bolean--. The configuration is immutable: once the object is created, the configuration will never change.

public class Configuration {
    private final boolean abilityOne;
    private final boolean abilityTwo;
    private final boolean abilityThree;
    private final boolean abilityFour;

    public Configuration (final boolean abilityOne, final boolean abilityTwo,
                          final boolean abilityThree, final boolean abilityFour) {
    this.configuration = ((1 * (abilityOne ? 1 : 0)) +
            (2 * (abilityTwo ? 1 : 0)) +
            (4 * (abilityThree ? 1 : 0)) +
            (8 * (abilityFour ? 1 : 0)));
 }

    public boolean isAbilityOne() {
        return((1 & this.configuration) > 0);
    }

    public boolean isAbilityTwo() {
        return((2 & this.configuration) > 0);
    }

    public boolean isAbilityThree() {
        return((4 & this.configuration) > 0);
    }

    public boolean isAbilityFour() {
        return((8 & this.configuration) > 0);
    }
}

Because of C / limited-hardware background, my next implementation (attempt at reducing memory footprint) was with an int used as a bit map: 1 -> first boolean, 2-> second, 4 -> third, 8-> fourth. This way I store an integer and the boolean functions I needed were like:

It works fine and it is quite memory efficient. But it is frowned upon by my Java-all-my-life colleagues.

The number of different configurations is limited (the combinations of boolean values), but the number of objects using them is very large. In order to decrease memory consumption I thought of some kind of "multi-singleton", enumeration or cached instances. And this is where I am now. What is best?


Solution

  • I think multiton pattern is the most efficient way to do this:

    public class Configuration {
    
        private static Map<Long, Configuration> configurations = new HashMap<>();
    
        private long key;
        private long value;
    
        public static Configuration getInstanse(long key, boolean... configs) {
            if (configurations.containsKey(key)) {
                return configurations.get(key).setConfigs(configs);
            }
            Configuration configuration = new Configuration(key, configs);
            configurations.put(key, configuration);
            return configuration;
        }
    
        // Max number of configs.length is 64
        private Configuration(long key, boolean... configs) {
            this.key = key;
            setConfigs(configs);
        }
    
        private Configuration setConfigs(boolean[] configs) {
            this.value = 0L;
            boolean config;
            for (int i = 0; i < configs.length; i++) {
                config = configs[i];
                this.value = this.value | (config ? (1L << i) : 0L);
            }
        }
    
        public long getKey() {
            return key;
        }
    
        public boolean getConfig(int place) {
            return (value & (1L << place)) == (1L << place);
        }
    }