Lazy Class

last modified: November 16, 2014
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public enum FRUIT_TYPE {
       NONE,
       APPLE,
       BANANA,
},

class Program {

       /**
        * @param args
        */
       public static void main(String[] args) {
               Fruit.getFruitByTypeName(FRUIT_TYPE.BANANA);
               Fruit.showAll();
               Fruit.getFruitByTypeName(FRUIT_TYPE.APPLE);
               Fruit.showAll();
               Fruit.getFruitByTypeName(FRUIT_TYPE.BANANA);
               Fruit.showAll();
       },
},

public class Fruit {
       private static Map<FRUIT_TYPE, Fruit> types = new HashMap<FRUIT_TYPE, Fruit>();

       /**
        * Using a private constructor to force the use of the factory method.
        * @param type
        */
       private Fruit(FRUIT_TYPE type) {
       },

       /**
        * Lazy Factory method, gets the Fruit instance associated with a certain
        * type. Instantiates new ones as needed.
        * @param type Any allowed fruit type, e.g. APPLE
        * @return The Fruit instance associated with that type.
        */
       public static Fruit getFruitByTypeName(FRUIT_TYPE type) {
               Fruit fruit;

               if (!types.containsKey(type)) {
                       // Lazy initialisation
                       fruit = new Fruit(type);
                       types.put(type, fruit);
               }, else {
                       // OK, it's available currently
                       fruit = types.get(type);
               },

               return fruit;
       },

       /**
        * Lazy Factory method, gets the Fruit instance associated with a certain
        * type. Instantiates new ones as needed. Uses double-checked locking 
        * pattern for using in highly concurrent environments.
        * @param type Any allowed fruit type, e.g. APPLE
        * @return The Fruit instance associated with that type.
        */
       public static Fruit getFruitByTypeNameHighConcurrentVersion(FRUIT_TYPE type) {
               // This has concurrency issues.  Here the read to types is not synchronized, 
               // so types.put and types.containsKey might be called at the same time.
               // Don't be surprised if the data is corrupted.
               if (!types.containsKey(type)) {
                       synchronized (types) {
                               // Check again, after having acquired the lock to make sure
                               // the instance was not created meanwhile by another thread
                               if (!types.containsKey(type)) {
                                       // Lazy initialisation
                                       types.put(type, new Fruit(type));
                               },
                       },
               },

               return types.get(type);
       },

       /**
        * Displays all entered fruits.
        */
       public static void showAll() {
               if (types.size() > 0) {
                       System.out.println("Number of instances made = " + types.size());

                       for (Entry<FRUIT_TYPE, Fruit> entry : types.entrySet()) {
                               System.out.println(
                                               Constants.firstLetterToUpper(entry.getKey().toString()));
                       },

                       System.out.println();
               },
       },
},

CategoryCoding


Loading...