el aprendizaje de guayaba (a): patrón de observador

El patrón de observador patrones de diseño es de comportamiento muy comunes. En la implementación de Java de forma primitiva, el espectador se da cuenta de la interfaz Observer, heredada observador observable.

Aquí el uso de la API de Java para escribir una aplicación sencilla.

Código de observador:

public class MyObserver implements Observer {

    public void update(Observable o, Object arg) {
        if (o instanceof MyObservable){
            System.out.println(arg);
        }

    }
}

El observado:

public class MyObservable extends Observable {

    @Override
    public void notifyObservers(Object message){
        super.setChanged();
        super.notifyObservers(message);
    }

}

 

categorías de temas ligados:

public class Subject {

    private Observable observable = new MyObservable();

    public void registerObserver(MyObserver observer) {
        observable.addObserver(observer);
    }

    public void removeObserver(MyObserver observer) {
        observable.deleteObserver(observer);
    }

    public void notifyObservers(String message) {
        observable.notifyObservers(message);
    }

}

código de ensayo

public static void main(String[] args) {
        Subject subject = new Subject();
        MyObserver observer = new MyObserver();
        subject.registerObserver(observer);
        subject.notifyObservers("hi, I am subject Observable");
}

aplicación java, si se logra el observador mediante un procesamiento de mensajes asíncronos, y el código de servicio se acoplan entre sí código inhábil.

observador de guayaba encapsula modo Java, y conveniente asíncrono apoyo. hablar es barato, vistazo al código:

Definición 2 espectadores:

public class AObserver {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Subscribe
    public void handleMessage(String msg){
        logger.info("a obsesrver receive message:{}", msg);
    }
}
public class BObserver {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Subscribe
    public void handleMessage(String msg){
        logger.info("b obsesrver receive message:{}", msg);
    }
}

 

clase EventBusUtil

public class EventBusUtil {

    public static EventBus getEventBus(){
        return EventBusFactory.getAsyncInstance();
    }

    public static class EventBusFactory{
        private static EventBus asyncEventBus = new AsyncEventBus(LocalThreadPoolExecutor.getExecutor());
        private static EventBus syncEventBus = new AsyncEventBus(MoreExecutors.directExecutor());

        public static EventBus getAsyncInstance(){
            return asyncEventBus;
        }

        public static EventBus getyncInstance(){
            return syncEventBus;
        }

    }
}

Nota: MoreExecutors.directExecutor) aparece (grupo de subprocesos que sean, de hecho, es de un solo subproceso, vistazo a la anotación de código fuente:

Código de ensayo:

public class TestEventBus{

    public static void main(String[] args){
        EventBus eventBus = EventBusUtil.getEventBus();
        eventBus.register(new AObserver());
        eventBus.register(new BObserver());

        for (int j = 0; j < 2; j ++){
            eventBus.post("hi, observer" + j);
        }
    }
}

La siguiente vistazo a la implementación de la guayaba:

1) registro de EventBus, cualquier objeto puede ser registrado como un observador

  /**
   * Registers all subscriber methods on {@code object} to receive events.
   *
   * @param object object whose subscriber methods should be registered.
   */
  public void register(Object object) {
    subscribers.register(object);
  }

 

Todo el enfoque de clase observadores a los eventos del monitor añadir un comentario @Subscribe tiempo, el registro, Canadá se parecerá a este método anotada a continuación, registrar, consulte el siguiente código

método findAllSubscribers

/** Registers all subscriber methods on the given listener object. */
  void register(Object listener) {
//查找所有包含@Subscribe注解的方法
    Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);

    for (Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
      Class<?> eventType = entry.getKey();
      Collection<Subscriber> eventMethodsInListener = entry.getValue();

      CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);

      if (eventSubscribers == null) {/还没有注册观察者
        CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<>();
        eventSubscribers =
            MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet);
      }

      eventSubscribers.addAll(eventMethodsInListener);
    }
  }

2) EventBus de notificación

/**
   * Posts an event to all registered subscribers. This method will return successfully after the
   * event has been posted to all subscribers, and regardless of any exceptions thrown by
   * subscribers.
   *
   * <p>If no subscribers have been subscribed for {@code event}'s class, and {@code event} is not
   * already a {@link DeadEvent}, it will be wrapped in a DeadEvent and reposted.
   *
   * @param event event to post.
   */
  public void post(Object event) {
    Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
    if (eventSubscribers.hasNext()) {
      dispatcher.dispatch(event, eventSubscribers);
    } else if (!(event instanceof DeadEvent)) {
      // the event had no subscribers and was not itself a DeadEvent
      post(new DeadEvent(this, event));
    }
  }

Como puede verse en el código anterior notificado por dispatcher.dispatch método, el código de este método de ver los siguientes códigos:

@Override
    void dispatch(Object event, Iterator<Subscriber> subscribers) {
      checkNotNull(event);
      while (subscribers.hasNext()) {
        queue.add(new EventWithSubscriber(event, subscribers.next()));
      }

      EventWithSubscriber e;
      while ((e = queue.poll()) != null) {
        e.subscriber.dispatchEvent(e.event);
      }
    }

Los códigos anteriores se puede ver, el mensaje de evento visor de eventos de abonado y se empaquetan en un objeto complicado en la cola, y luego dejar que el procesamiento de mensajes dequeue observador gatillo.

/** Dispatches {@code event} to this subscriber using the proper executor. */
  final void dispatchEvent(final Object event) {
    executor.execute(
        new Runnable() {
          @Override
          public void run() {
            try {
              invokeSubscriberMethod(event);
            } catch (InvocationTargetException e) {
              bus.handleSubscriberException(e.getCause(), context(event));
            }
          }
        });
  }

Esto es lo que pasa en el grupo de subprocesos al declarar variables EventBus grupo de subprocesos. El último evento desencadena mediante la reflexión de Java.

/**
   * Invokes the subscriber method. This method can be overridden to make the invocation
   * synchronized.
   */
  @VisibleForTesting
  void invokeSubscriberMethod(Object event) throws InvocationTargetException {
    try {
      method.invoke(target, checkNotNull(event));
    } catch (IllegalArgumentException e) {
      throw new Error("Method rejected target/argument: " + event, e);
    } catch (IllegalAccessException e) {
      throw new Error("Method became inaccessible: " + event, e);
    } catch (InvocationTargetException e) {
      if (e.getCause() instanceof Error) {
        throw (Error) e.getCause();
      }
      throw e;
    }
  }

análisis de código de aquí, la guayaba detalla vistazo al código aquí:

https://github.com/google/guava

texto código de ejemplo ver aquí

https://github.com/jinjunzhu/myguava.git

 

Sin atención personal bienvenida al público, aprender juntos, crecer juntos

Publicado 33 artículos originales · ganado elogios 2 · Vistas a 40000 +

Supongo que te gusta

Origin blog.csdn.net/zjj2006/article/details/104914398
Recomendado
Clasificación