l'apprentissage de la goyave (a): Motif observateur

Le modèle d'observation est design patterns de comportement très communs. Dans la mise en œuvre de Java forme primitive, le spectateur réalise l'interface Observer, héritée observateur Observable.

Ici, l'utilisation de Java api écrire une implémentation simple.

Code de l'observateur:

public class MyObserver implements Observer {

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

    }
}

Le observé:

public class MyObservable extends Observable {

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

}

 

Rebond Catégories de sujets:

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);
    }

}

Code d'essai

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

la mise en œuvre java, si l'observateur est réalisé au moyen d'un traitement asynchrone de messages, et le code de service sera couplé ensemble du code non commercial.

observateur goyave encapsule mode Java, et asynchrone de soutien pratique. parler ne coûte pas cher, regardez le code:

Définition 2 téléspectateurs:

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);
    }
}

 

classe 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;
        }

    }
}

Note: MoreExecutors.directExecutor () pool de threads semble être, en fait, est mono-thread, regardez l'annotation du code source:

Code d'essai:

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);
        }
    }
}

L'aspect suivant à la mise en œuvre de la goyave:

1) l'enregistrement de EventBus, tout objet peut être enregistré comme un observateur

  /**
   * 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);
  }

 

Tous les observateurs approche de classe aux événements moniteur ajouter un commentaire @Subscribe, le temps d'inscription, Canada ressemblera cette méthode annotée puis vous inscrire, consultez le code suivant

procédé 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 notification

/**
   * 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));
    }
  }

Comme on peut le voir dans le code ci-dessus notifié par dispatcher.dispatch méthode, le code de cette méthode voir les codes suivants:

@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);
      }
    }

Les codes ci-dessus peuvent être vus, le message d'événement abonné Observateur d'événements et emballés dans un objet complexe dans la file d'attente, puis laissez le déclencheur d'observateur traitement des messages dequeue.

/** 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));
            }
          }
        });
  }

Voici ce que nous avons passé dans la piscine de fil lors de la déclaration de pool de threads de les variables. Le dernier événement déclenche en utilisant la réflexion 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;
    }
  }

Code analyse ici, goyave regard détaillé sur le code ici:

https://github.com/google/guava

texte du code échantillon voir ici

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

 

Aucune attention de bienvenue personnelle au public, apprennent ensemble, grandir ensemble

Publié 33 articles originaux · a gagné les éloges 2 · vues 40000 +

Je suppose que tu aimes

Origine blog.csdn.net/zjj2006/article/details/104914398
conseillé
Classement