Understanding JAVA event processing mechanism from scratch (2), from scratch java
The example in section 1 is too simple: Understanding the JAVA event processing mechanism from scratch (1). It makes everyone feel that such code is useless. But there is no way. We should continue to write this useless code and then introduce the truly beneficial code in the next stage.
I. Introduction to the event-driven model
If we want to say that the event-driven model is an upgraded version of the observer model, we need to talk about the corresponding relationship:
Listener for The Observer (student)
Event source (Instructor) of the observed object)
The event source generates an event and the listener listens to the event. A friend of mine may say, "What is an event? Listen to it? What is an event?
Don't panic. If we use code, the event source is a class, and the event is the lines of business code in the event source. There are a total of four types of events, namely, the event source (namely the teacher, namely the observer), the event, the listener interface, and the specific listener (namely the student, that is, the observer ).
As mentioned in the first section of the previous article, JDK certainly has a ready-made event model class. Let's take a look at it one by one.
First, let's look at the listener (that is, the student, that is, the observer. Don't bother me and keep reminding me in parentheses. This is to keep increasing your impression ),
package java.util;
/**
* A tagging interface that all event listener interfaces must extend.
* @since JDK1.1
*/
public interface EventListener {
}
It can't be simpler, right? Even a declared method doesn't. What does it mean? Do you still remember the trace shape in the object-oriented model? So its significance is to tell all callers that I am a listener.
Let's take a look at the event source (that is, the instructor, that is, the observer ),
package java.util;
/**
* <p>
* The root class from which all event state objects shall be derived.
* <p>
* All Events are constructed with a reference to the object, the "source",
* that is logically deemed to be the object upon which the Event in question
* initially occurred upon.
*
* @since JDK1.1
*/
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
/**
* 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 a String representation of this EventObject.
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
This class is also very simple. If the upper class and result in the Observer mode carry many logic and many methods, the upper class and interface in the event-driven model cannot see anything. Yes,
In the event-driven model, JDK designers make the highest level of abstraction, that is, to make the upper class only representative: I am an event source, or, I am a listener!
II. The event-driven model version assigned by the instructor
Old rules, let's first give a class diagram:
Then, implement the Code:
Observer interface (student ). In the event-driven model, there is only one interface without any method, EventListener, so we can first implement an interface of our own. To be consistent with the previous code, the method we declare in this interface is also called update. Note that we can also choose not to use this name, or even add other method declarations, depending on our business needs.
package com.zuikc.events;
import java.util.Observable;
public interface HomeworkListener extends java.util.EventListener {
public void update(HomeworkEventObject o, Object arg);
}
Then the observer class (student) is implemented as follows:
Package com. zuikc. events;
Public class Student implements HomeworkListener {
Private String name;
Public Student (String name ){
This. name = name;
}
@ Override
Public void update (HomeworkEventObject o, Object arg ){
Teacher teacher = o. getTeacher ();
System. out. printf ("Students % s observed (actually notified) % s assigned homework" % s "\ n", this. name, teacher. getName (), arg );
}
}
Is there any change in the previous article?
Then the class of event source is implemented as follows:
package com.zuikc.events;
public class HomeworkEventObject extends java.util.EventObject {
public HomeworkEventObject(Object source) {
super(source);
}
public HomeworkEventObject(Teacher teacher) {
super(teacher);
}
public Teacher getTeacher(){
return (Teacher) super.getSource();
}
}
In this class, it refers to the getTeacher method, which encapsulates the getSource method of the parent class EventObject. Theoretically, the getSource method of the parent class is also feasible, but it is more readable by encapsulating the Child class again.
Then, our category class is as follows:
Package com. zuikc. events;
Import java. util .*;
Public class Teacher {
Private String name;
Private List <String> homeworks;
/*
* The Listener class maintains a list of its own listeners (students). Why?
* In observer mode, the instructor is an observer and inherits from java. util. Observable. the Observable includes this list.
* Now we do not have this list, so we need to create
*/
Private Set <HomeworkListener> homeworkListenerList;
Public String getName (){
Return this. name;
}
Public Teacher (String name ){
This. name = name;
This. homeworks = new ArrayList <String> ();
This. homeworkListenerList = new HashSet <HomeworkListener> ();
}
Public void setHomework (String homework ){
System. out. printf ("% s assigned the job % s \ n", this. name, homework );
Homeworks. add (homework );
HomeworkEventObject event = new HomeworkEventObject (this );
/*
* In the observer mode, we call the observer yobservers of the Observable directly to notify the observer.
* Now we can only notify ourselves ~~
*/
For (HomeworkListener listener: homeworkListenerList ){
Listener. update (event, homework );
}
}
Public void addObserver (HomeworkListener homeworkListener ){
HomeworkListenerList. add (homeworkListener );
}
}
This class is a little longer. There are several points worth noting:
First, Teacher has no parent class, and Teacher is encapsulated into HomeworkEventObject as the Source in the event Source. There is nothing wrong with this. The business objects are isolated from the Framework Code, and the decoupling is very good. But because of this, we need to maintain a Student list in Teacher. Therefore, we can see the homeworkListenerList variable.
Second, in the Observer mode, we directly call the observer yobservers of Observable to notify the observer. Now we can only rely on ourselves, so we can see this code,
For (HomeworkListener listener: homeworkListenerList ){
Listener. update (event, homework );
}
There is no such problem. Let's continue to look at the client code:
Package com. zuikc. events;
Import java. util. EventListener;
Public class Client {
Public static void main (String [] args ){
Student student1 = new Student ("Zhang San ");
Student student2 = new Student ("Li Si ");
Teacher teacher1 = new Teacher ("zuikc ");
Teacher1.addObserver (student1 );
Teacher1.addObserver (student2 );
Teacher1.setHomework ("event mechanism second day job ");
}
}
The result is as follows:
From the client perspective, we have hardly changed anything. It is exactly the same as the client code in the Observer mode, but we use the event mechanism in the internal implementation mechanism.
Let's summarize the differences between the observer mode and the event-driven model:
1: The Event source no longer inherits any mode or the parent class of the model itself, and completely decouples the Business Code;
2: In the event model, each listener (observer) must implement its own interface. That's right. Let's look at our mouse events. Table sharding involves clicking, double-clicking, and moving events, which increase the flexibility of the Code;
In any case, we have implemented an event-driven model example with a bunch of code. Although it is of no practical use, it also explains the principle. In the next section, let's take a look at the code that is a little complex and looks very useful!