---

2015/10/25

layout: post
title: "Refactoring Java Using a Functional Interface and Generics"
category: Reading Notes

tags: ["读文章", "Java", "代码重构"]

{% include JB/setup %}

Original Code

public V get(final K key)
{
  Session s;
  try {
      s = oGrid.getSession();
      ObjectMap map = s.getMap(cacheName);
      return (V) map.get(key);
  }
  catch (ObjectGridException oge)
  {
      throw new RuntimeException("Error performing cache operation", oge);
  }
  finally
  {
      if (s != null)
          s.close();         
  }    
  return null;
}      

public void put(final K key, final V value)
{
  Session s;
  try {
      s = oGrid.getSession();
      ObjectMap map = s.getMap(cacheName);
      map.upsert(key, value);
  }
  catch (ObjectGridException oge)
  {
      throw new RuntimeException("Error performing cache operation", oge);
  }
  finally
  {
      if (s != null)
          s.close();             
  }            
}

public Map<K, V> getAll(Set<? extends K> keys)
{
  final List<V> valueList = new ArrayList<V>();
  final List<K> keyList = new ArrayList<K>();
  keyList.addAll(keys);

  Session s;
  try {
      s = oGrid.getSession();
      ObjectMap map = s.getMap(cacheName);
      valueList = map.getAll(keyList);
  }
  catch (ObjectGridException oge)
  {
      throw new RuntimeException("Error performing cache operation", oge);
  }
  finally
  {
      if (s != null)
          s.close();             
  }

  Map<K, V> map = new HashMap<K, V>();
  for(int i = 0; i < keyList.size(); i++) {
      map.put(keyList.get(i), valueList.get(i));
  }
  return map;
}

The problem:this block of code is duplicate

Session s;
try {
  s = oGrid.getSession();
  ObjectMap map = s.getMap(cacheName);
  // Some small bit of business logic goes here
}
catch (ObjectGridException oge)
{
  throw new RuntimeException("Error performing cache operation", oge);
}
finally
{
  if (s != null)
      s.close();             
}

The refactored code:

interface Executable<T> {
  public T execute(ObjectMap map) throws ObjectGridException;
}

private <T> T executeWithMap(Executable<T> ex)
{
  Session;
  try {
      s = oGrid.getSession();
      ObjectMap map = s.getMap(cacheName);
      // Execute our business logic
      return ex.execute(map);
  }
  catch (ObjectGridException oge)
  {
      throw new RuntimeException("Error performing cache operation", oge);
  }
  finally
  {
      if (s != null)
          s.close();             
  }
}

public V get(final K key)
{
  return executeWithMap(new Executable<V>() {
      public V execute(ObjectMap map) throws ObjectGridException
      {
          return (V) map.get(key);
      }
  });              
}      

public void put(final K key, final V value)
{
  executeWithMap(new Executable<Void>() {
      public Void execute(ObjectMap map) throws ObjectGridException
      {
          map.upsert(key, value);
          return null;
      }
  });              
}

Reference:

http://www.michaelbrameld.com/blog/2013/11/02/refacoring-java-generic-functional-interface/