Java: ServiceLoader decouple API and Implementation

Un sencillo ejemplo del uso de ServiceLoader, muy útil para para crear aplicaciones extensibles a la vez que separamos las interfaces de sus implementaciones en diferentes empaquetados (jar).

La factoría que usa el ServiceLoader y la interface común (ambos ficheros en storage-api.jar):

package com.acme;

import java.util.ServiceLoader;

public class StorageFactory {
  public static Storage getInstance() {
    for (Storage storage : ServiceLoader.load(Storage.class)) {
      return storage;
    }
    throw new UnsupportedOperationException("No implementation found");
  }
}

La interface que deben implementar todos los servicios:

package com.acme;

public interface Storage {
  void put(String key, String value);

  String get(String key);
}

Un ejemplo de implementación en memoria (ambos ficheros en storage-memory.jar):

package com.acme;

import java.util.concurrent.ConcurrentHashMap;

public class MemoryStorage implements Storage {
  private final ConcurrentHashMap<String, String> map;

  public MemoryStorage() {
    map = new ConcurrentHashMap<String, String>();
  }

  @Override
  public void put(final String key, final String value) {
    map.put(key, value);
  }

  @Override
  public String get(final String key) {
    return map.get(key);
  }
}

El fichero META-INF/services/com.acme.Storage

com.acme.MemoryStorage

Otra implementación estilo /dev/null (ambos ficheros en storage-null.jar):

package com.acme;

public class NullStorage implements Storage {
  @Override
  public void put(final String key, final String value) {
  }

  @Override
  public String get(final String key) {
    return null;
  }
}

El fichero META-INF/services/com.acme.Storage

com.acme.NullStorage

Y para acabar, el código de prueba:

package com.acme;

public class TestStorage {
  public static void main(final String[] args) throws Throwable {
    final Storage storage = StorageFactory.getInstance();
    storage.put("data", "hello world");
    System.out.println(storage.get("data"));
  }
}

Referencias:
java.util.ServiceLoader

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: