Tengo una clase TrafficMonitor, dentro de la clase, tengo un método estático de fábrica para devolver una instancia de esta clase:

public class TrafficMonitor {
   private String busNumber;
   //private constructor
   private TrafficMonitor(String busNumber) {
       this.busNumber = busNumber;
   }

   // static factory method to return a instance of this class
   public static TrafficMonitor forBus(String busNumber) {
       // how to make sure one instance per busNumber???
       return new TrafficMonitor(busNumber);
   }

}

No quiero que el TrafficMonitor sea un singleton en general. Pero dentro del método de fábrica estática forBus(String busNumber), me gustaría asegurarme de que se devuelva la misma instancia de TrafficMonitor para el mismo busNumber. Eso es "singleton" por busNumber. ¿Cómo lograrlo?

Por ejemplo, el siguiente código debería usar la misma instancia de TrafficMonitor:

// monitor1 and monitor2 are referring to the same instance
TrafficMonitor monitor1 = TrafficMonitor.forBus("123");
TrafficMonitor monitor2 = TrafficMonitor.forBus("123");

El siguiente código debe usar diferentes instancias de TrafficMonitor:

// monitor1 and monitor2 are two different instances
TrafficMonitor monitor1 = TrafficMonitor.forBus("123");
TrafficMonitor monitor2 = TrafficMonitor.forBus("456");

Y quiero que el método de fábrica estática también sea seguro para subprocesos. Eso es si dos subprocesos lo llaman para el mismo número de bus, dos subprocesos también deberían usar la misma instancia.

3
user842225 13 oct. 2019 a las 17:58

1 respuesta

La mejor respuesta

Agrega instancias a un mapa estático. Utilice computeIfAbsent para devolver la instancia existente si la clave ya existe o crear una nueva si no existe.

Un ConcurrentMap garantiza la seguridad del hilo.

private static ConcurrentMap<String, TrafficMonitor> instances = new ConcurrentHashMap<>();

public static TrafficMonitor forBus(String busNumber) {
    return instances.computeIfAbsent(busNumber, TrafficMonitor::new);
}
4
John Kugelman 13 oct. 2019 a las 15:05