An example analysis observer model and its application in Java design pattern development _java

Source: Internet
Author: User
Tags abstract class manager event listener getmessage mutex static class

I. The definition OF the Observer Model (OBSERVER):

The Observer pattern is also known as the subscription-publish pattern, in which a target object manages all the observer objects that are dependent on it and actively notifies itself when its state changes. This is usually done by calling the methods provided by the various observers. This pattern is often used for event-handling systems.

1, the general structure of the observer model

First look at the class diagram description of the Observer pattern:

The role of the observer pattern is as follows:

Subject (Abstract Theme Interface): Defines a series of actions on the observer list in the subject class, including additions, deletions, notifications, and so on.
Concrete Subject (Specific topic Class):
Observer (Abstract Observer Interface): Defines the observer's acceptance action on the subject class update state.
Concreteobserver (Specific Observer Class): The realization of the Observer interface to update the subject class notification and other logic.
As you can see from this class diagram, a list of classes that implement the Observer interface is maintained in the subject class, and the subject class makes a series of additions and deletions to the viewer through this list. The Observer class can also actively invoke the Update method to understand the status update information for the subject class.

The above class diagram describes only the basic observer mode of thought, there are many deficiencies. For example, as observers can also actively subscribe to a certain type of topic. The following example will make some changes to apply the specific business logic.

2. Example of observer mode

We build an observer and subject class, and the observer can actively subscribe to the topic or cancel the topic. Subject-Class unification is managed by a subject manager. The class diagram is given below:

Subject:

Public interface Subject {//register a Observer public void register (Observer Observer);
  Remove a Observer public void remove (Observer Observer);
  Notify all observers of the public void Notifyobservers ();
Gets the message public String getMessage () to be published by the subject class.
  } Concertesubject:public class Mysubject implements Subject {private list<observer> observers;
  private Boolean changed;
  Private String message;
  Object lock, for synchronizing update Observer list private final Object mutex = new Object ();
    Public Mysubject () {observers = new arraylist<observer> ();
  Changed = FALSE; @Override public void Register (Observer Observer) {if (Observer = null) throw new NullPointerException ()
      ;
  Guaranteed not to repeat if (!OBSERVERS.CONTAINS (Observer)) OBSERVERS.ADD (Observer);
  @Override public void Remove (Observer Observer) {observers.remove (Observer);
    @Override public void Notifyobservers () {//Temp list list<observer> tempobservers = null;
     Synchronized (mutex) { if (!changed) return;
      Tempobservers = new arraylist<> (this.observers);
    This.changed = false;
    for (Observer obj:tempobservers) {obj.update (); }//Subject class publishing new message public void makechanged (String message) {System.out.println ("The Subject Make a change:" + mess
    Age);
    this.message = message;
    This.changed = true;
  Notifyobservers ();
  @Override public String GetMessage () {return this.message;
 }
}

When Concertesubject makes an update, it notifies all the observers in the list and calls the Observer Update method to implement the logic after the notification is received. Notice here the sync block in the notifyobservers. In the case of multithreading, in order to avoid the topic class release notification, other threads to the Observer list additions and deletions operations, synchronization block with a temporary list to get the current list of observers.

Subjectmanagement: Theme class Manager

public class Subjectmanagement {
  //a record name-theme class Map
  private map<string, subject> subjectlist = new HashMap <string, subject> ();
  public void Addsubject (String name, Subject Subject) {
    subjectlist.put (name, Subject);
  }
  public void Addsubject (Subject Subject) {
    subjectlist.put (Subject.getclass (). GetName (), Subject);
  Public Subject Getsubject (String subjectname) {return
    subjectlist.get (subjectname);
  }
  public void Removesubject (String name, Subject Subject) {
  } public
  void Removesubject (Subject Subject) {
  //singleton
  Private subjectmanagement () {} public
  static Subjectmanagement getinstance () {
    return subjectmanagementinstance.instance;
  }
  private static class Subjectmanagementinstance {
    static final subjectmanagement instance = new Subjectmanagement ();
  }
}

The purpose of the Theme class manager is to get an instance object for this topic when the Observer subscribes to a topic.

Observer:

Public interface Observer {public
  void Update ();
  public void Setsubject (Subject Subject);
}
Concerteobserver: Public
class Myobserver implements Observer {
  private Subject Subject;
  Get the notify message from concentrate Subject
  @Override public
  Void Update () {
    String message = Subject. GetMessage ();
    System.out.println ("from Subject" + Subject.getclass (). GetName ()
        + ' message: ' + message);
  }
  @Override public
  void Setsubject (Subject Subject) {
    this.subject = Subject;
  }
  Subcirbe some Subject public
  void Subscribe (String subjectname) {
    subjectmanagement.getinstance (). Getsubject (subjectname). Register (this);
  Cancel Subcribe public
  void Cancelsubcribe (String subjectname) {
    subjectmanagement.getinstance (). Getsubject (subjectname). Remove (this);
  }

Test: We abstract the subject class and the observer into the writer and the reader

public class Observertest {
  private static mysubject writer;
  @BeforeClass public
  static void Setupbeforeclass () throws Exception {
    writer = new Mysubject ();
    Add a writer named Linus
    subjectmanagement.getinstance (). Addsubject ("Linus", writer);
  @Test public
  void Test () {
    //define several readers
    myobserver reader1 = new Myobserver ();
    Myobserver reader2 = new Myobserver ();
    Myobserver Reader3 = new Myobserver ();
    Reader1.setsubject (writer);
    Reader2.setsubject (writer);
    Reader3.setsubject (writer);
    Reader1.subscribe ("Linus");
    Reader2.subscribe ("Linus");
    Reader3.subscribe ("Linus");
    Writer.makechanged ("I have a new Changed");
    Reader1.update ();
  }

The above is a small example of the observer pattern. It can be seen that each topic class maintains a corresponding list of observers, which can be further abstracted from the abstract level of the specific topic and put into an abstract class to implement to jointly maintain a list, of course, depending on the actual business logic.

Second, the listener in the servlet

Before talking about the listener in the servlet, let's talk about another form of the observer pattern-the event-driven model. As with the subject role of the observer pattern mentioned above, the event-driven model includes an event source, a specific event, a listener, and a specific listener.
The listener in the servlet is a typical event-driven model.
JDK has a set of event-driven classes, including a unified listener interface and a unified source of events, the source code is as follows:

/**
 * A tagging interface The all event listener interfaces must.
 * @since JDK1.1 * * * public
interface EventListener {
}

This is a flag interface that the JDK requires that all listeners must inherit this interface.

public class EventObject implements java.io.Serializable {private static final long Serialversionuid = 551607534962065
  3480L;
   /** * The object on which the Event initially occurred.
  * * protected transient Object source;
   /** * Constructs a prototypical Event.
   * @param source the object on which the Event initially occurred.
   * @exception illegalargumentexception if source is null.
    */Public EventObject (Object source) {if (source = = null) throw new IllegalArgumentException ("null source");
  This.source = source;
   }/** * The object on which the Event initially occurred.
   * * @return The object on which the Event initially occurred.
  */Public Object GetSource () {return source;
   }/** * Returns a String representation of this eventobject.
   * * @return A String representation of this eventobject.
  */Public String toString () {return getclass () getName () + "[source=" + source + "]";
 }
}

Evenobject is a unified source of events that the JDK provides us with. The Evenobject class defines an event source and a Get method that gets the event source.

The following is an analysis of the servlet listener running process.

1, the composition of the Servlet listener

Currently, there are 6 types of listener interfaces for two types of events in the servlet, as shown in the following illustration:

The following table is the specific triggering scenario:

2, a specific listener trigger process

Let's take servletrequestattributelistener as an example to analyze the event-driven process here.

First in a servlet, when HttpServletRequest calls the Setattrilbute method, it is actually the Org.apache.catalina.connector.request#setattrilbute method that is invoked. Let's look at its source code:

public void setattribute (String name, Object value) {
    ...
    The above logical code has been omitted
    //Here is the notification listener
    notifyattributeassigned (name, value, OldValue);
  }

The following is the source code for notifyattributeassigned (String name, object value, Object OldValue)

private void notifyattributeassigned (String name, object value, Object OldValue) {//From the container gets the listener that is defined in the WebApp
    Example Object listeners[] = Context.getapplicationeventlisteners (); if ((listeners = null) | | (listeners.length = 0))
    {return;
    Boolean replaced = (OldValue!= null);
    Create a related event object servletrequestattributeevent event = null;  if (replaced) {event = new Servletrequestattributeevent (Context.getservletcontext (), Getrequest (), name,
    OldValue); else {event = new Servletrequestattributeevent (Context.getservletcontext (), Getrequest (), name, value)
    ; //traverse the list of all listeners, find the listener for the corresponding event for (int i = 0; i < listeners.length; i++) {if (!) (
      Listeners[i] instanceof Servletrequestattributelistener)) {continue; //Call listener method to implement listener operation Servletrequestattributelistener Listener = (servletrequestattributelistener) List
      Eners[i];
          try {if (replaced) {Listener.attributereplaced (event);
        else {listener.attributeadded (event);
        A catch (Throwable t) {exceptionutils.handlethrowable (t);
        Context.getlogger (). Error (Sm.getstring ("coyoterequest.attributeevent"), T); Error valve'll pick this exception up and display it to user attributes.put (requestdispatcher.error_exception
      , t);
 }
    }
  }

The above example clearly shows how the Servletrequestattributelistener is invoked. Users only need to implement the listener interface on the line. The listener in the servlet almost covers events of interest to the servlet throughout its lifecycle, and flexible use of these listenser can make the program more flexible.

III. Integrated Examples
For example, if you've seen TVB's robbers, you know how undercover works. Generally a police officer may have several undercover, sneak into the enemy inside, to pry information, undercover completely rely on the instructions of his leader to work, the leadership said a few actions, he must follow the time to carry out, if the action time change, he will immediately change his time to cooperate with the action. The leader sent two undercover men to infiltrate the enemy's interior. Then the leader is equivalent to the abstract theme, and Inspector Officer John this person sent two undercover dick and Wan Wang, John is equivalent to a specific theme, undercover equivalent to the abstract observer, the two undercover is Dick and Harry is a specific observer, sent this action is equivalent to the observer in the subject of registration. So the class diagram is as follows:

Implemented using JAVAAPI, the code is described as follows:

Package observer; 
 
Import java.util.List; 
Import java.util.Observable; 
Import Java.util.Observer; 
/** 
 * Description: Police John * * * Public 
class Police extends observable { 
 
  private String time; 
  Public Police (list<observer> List) { 
    super (); 
    for (Observer o:list) { 
      addobserver (o); 
    } 
  } 
  public void Change (String time) { 
    this.time = time; 
    Setchanged (); 
    Notifyobservers (This.time); 
  } 
 
Package observer; 
 
Import java.util.Observable; 
Import Java.util.Observer; 
/** 
 * Description: Undercover A */public 
class Undercovera implements Observer { 
 
  private String time; 
  @Override public 
  void update (Observable o, Object Arg) {Time 
    = (String) arg; 
    System.out.println ("Undercover a received message, Action time:" +time); 
  } 
 
 
 

Package observer; 
 
Import java.util.Observable; 
Import Java.util.Observer; 
/** 
 * Description: Undercover b */public 
class Undercoverb implements Observer { 
  private String time; 
  @Override public 
  void update (Observable o, Object Arg) {Time 
    = (String) arg; 
    System.out.println ("Undercover B received message, Action time:" +time); 
  } 
 
 
 
 

Package observer; 
 
Import java.util.ArrayList; 
Import java.util.List; 
Import Java.util.Observer; 
/** 
 * Description: Test 
/public class Client { 
 
  /** 
   * @param args 
   /public 
  static void main (string[ ] { 
    Undercovera O1 = new Undercovera () args); 
    Undercoverb O2 = new Undercoverb (); 
    list<observer> list = new arraylist<> (); 
    List.add (O1); 
    List.add (O2); 
    Police subject = new Police (list); 
    Subject.change ("02:25"); 
    System.out.println ("=========== due to news, action time Advance ========="); 
    Subject.change ("01:05"); 
     
  } 
 
 

Test Run Results:

Undercover B received news, action time: 02:25
undercover A received news, action time: 02:25
=========== due to news, action time in advance =========
Undercover B received message, Action time: 01:05
undercover a received the message, the action time is: 01:05

Iv. Summary

The Observer pattern defines a one-to-many relationship between objects, and objects that depend on it are notified when the state of an object (observed) changes. Can be applied to publishing--subscriptions, changes--to update this business scenario.
In a loosely coupled way between the observer and the observed, the observer does not know the details of the observer and only knows that the observer implements the interface.
The event-driven model is more flexible, but it pays for the complexity of the system as we tailor a listener and event to each event source, which increases the burden on the system.

The core of the observer pattern is to distinguish roles, locate good observers and the observed, and they are many-to-many relationships. The key to achieving this is to establish a link between the observer and the observed, such as having a set in the Observer class that is used to store the observer and notify all observers when the detected changes. In the observer's method of construction, the observer is passed in and registers itself in the list of observers owned by the Observer, that is, the observers list.

1. Advantages of the Observer model:
(1) Abstract subjects depend only on the abstract observer
(2) Observer mode supports broadcast communication
(3) The Observer pattern separates the information generation layer from the response layer

2. Shortcomings of the Observer model:
(1) If a subject is registered by a large number of observers, it will cost a high price to notify all observers
(2) If the response of some observers is blocked, the entire notification process is blocked and other observers are not notified in time

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.