mardi 27 août 2019

Add a layer of mapping on a child class

I am trying to write a class that works as a type of map. The children of this class have layers of mapping on top of basic functionality. Something like the below:

public interface MyMap<K, V> {
  public V get(K key);
}

public interface Client<K, V> {
  public V fetch(K key);
}

public class ComplexKey<T> {

  private T _key;

  public ComplexKey(T key) {
    _key = key;
  }

  T getKey() {
    return _key;
  }
}

public class BasicMyMap<K, V> implements MyMap<K, V> {

  private final Client<K, V> _client;

  public BasicMyMap(Client<K, V> client) {
    _client = client;
  }
  @Override
  public V get(K key) {
    return _client.fetch(key);
  }
}

/**
 *
 * @param <MK> mapped key
 * @param <K> key
 * @param <V> value
 */
public class ComplexKeyMyMap<MK extends ComplexKey, K, V> implements BasicMyMap<MK, V> {

  private Function<K, MK> _mapper;

  public ComplexKeyMyMap(Client<MK, V> client, Function<K, MK> mapper) {
    super(client);
    _mapper = mapper;
  }

  public V get(K rawKey) {
    return super.get(_mapper.apply(rawKey));
  }
}

public static void main(String[] args) {
  BasicMyMap<String, String> basicMyMap = new BasicMyMap<>(key -> "success");
  assert "success".equals(basicMyMap.get("testing"));

  ComplexKeyMyMap<ComplexKey, String, String> complexKeyMyMap = new ComplexKeyMyMap<>(key -> "success", (Function<Object, ComplexKey>) ComplexKey::new);
  assert "success".equals(complexKeyMyMap.get("testing"));
}

In addition to the key mapping, I would like to add a layer for mapping the value that is returned as well.

So question is:

  1. What is the common approach to this problem? I have encountered this pattern multiple times and have not found a great solution.
  2. How can I achieve this such that the users of these classes can just rely on the MyMap interface definition.

Thanks for the help.

Aucun commentaire:

Enregistrer un commentaire