The example in the first section of "Understanding the JAVA Event Processing Mechanism from Scratch (1)" is too simple, so simple that everyone feels that such code is simply useless. But there is no way, we have to continue writing this useless code, and then lead to the next stage of really useful code.
1: A first look at the event-driven model
We want to say that the event-driven model is an upgraded version of the observer pattern, then we have to talk about the corresponding relationship:
The observer corresponds to the listener (student)
The observed corresponds to the event source (teacher)
The event source generates an event, and the event has an event Source, listener listens for events. Friends who love to talk about things may say, hey, what are generating events, monitoring events, and what exactly are events?
Don’t panic, if we use code to talk about things, the event is a class, and the event source is also a class. There are four categories involved in this, event source (i.e. teacher, i.e. observer), event (a class, see below, usually we end with Event or EventObject), listener interface, specific listener (i.e. students, i.e. observers).
As mentioned in the first section of our previous article, there are of course ready-made event model classes in the JDK. We might as well check them one by one.
First look at the listener (i.e. student, i.e. observer, please don’t find me annoying, keep dropping parentheses to remind everyone, this is to deepen your impression),
package java.util;
/**
* A tagging interface that all event listener interfaces must extend.
* @since JDK1.1
*/
public interface EventListener {
}
It couldn’t be simpler, right? There isn't even a declared method, so what's the point of its existence? Remember the upcasting in object-oriented, so its meaning is to tell all callers that I am a listener.
Let’s take a look at the event, that is, the class at the end of Event or EventObject, which contains the getSource method, which returns the event source (i.e. the teacher, the observer),
2: The event-driven model version of the assignment assigned by the teacherpackage java.util;
/**
*
* The root class from which all event state objects shall be derived.
*
* 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)
,, , @return The object on which the Event initially occurred.public Object getSource() {
}
return source;}
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";}
This The classes are also very simple. If the upper classes and results in the observer pattern also have a lot of logic and methods, then you can hardly see anything in the upper classes and interfaces in the event-driven model. That's right, in the
event-driven model, the designers of JDK have carried out the highest level abstraction, which is to let the upper class only represent: I am an event (containing event source), or, I It's a listener!
Old rules, let us first give the class diagram:
Then, the code implements it:
Observer interface (student). Since in the event-driven model, there is only one interface without any methods, EventListener, so we can first implement an interface of our own. In order to be consistent with the code in the previous article, the name of the method we declared in this interface is also called update. Note that of course we can not 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 implement the observer class (student), 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("Student %s observed (actually was notified) that %s assigned Assignment "%s" \n", this.name, teacher.getName(), arg);
}}
Compare with the previous article, are there any changes? ?
Then implement the event subclass, 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, the focus is on the getTeacher method, which Encapsulates the getSource method of the parent class EventObject to obtain the event source. Theoretically, it is also feasible for us to use the getSource method of the parent class, but re-encapsulating it in the subclass will make it more readable.
Then, then there is our teacher class, which is the event source, as follows:
package com.zuikc.events;
import java.util .*;
public class Teacher {
private String name;
private Listhomeworks;
/*
* The teacher class must maintain its own listener (student) list, why?
* In the observer pattern, the teacher is the observer, inherited from java.util.Observable, and Observable contains this list
* Now we don’t have this list, so we have to create one ourselves
* /
private SethomeworkListenerList; public String getName() {
return this.name;
}public Teacher(String name) {
this.name = name;
this.homeworks = new ArrayList();
this.homeworkListenerList = new HashSet();
}public void setHomework (String homework) {
System.out.printf("%s assigned homework %s \n", this.name, homework);
Homeworks.add(homework);
HomeworkEventObject event = new HomeworkEventObject(this);
/*
* In the observer pattern, we directly call the notifyObservers of Observable to notify the observed
* 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 slightly longer So a little bit, there are a few places worth noting:
The first place is that Teacher has no parent class. Teacher, as the event source Source in the event, is encapsulated into HomeworkEventObject. 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 list of Students in the Teacher ourselves, so we saw the variable homeworkListenerList.
Second, in the observer mode, we directly call the notifyObservers of Observable to notify the observed. Now we can only rely on ourselves, so we saw this code,
for (HomeworkListener listener : homeworkListenerList) {
listener.update(event, homework);
}
There is no problem at all, 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("李思");
Teacher teacher1 = new Teacher("zuikc");
teacher1.addObserver(student1);
teacher1.addObserver(student2);
teacher1.setHomework("Event mechanism homework for the next day");
}}
The results are as follows:
From the client's perspective, we have almost not changed anything at all. It is exactly the same as the client code in the observer mode, but internally As for the implementation mechanism, we use the event mechanism.
Now let’s summarize the differences between the observer pattern and the event-driven model:
1: The event source no longer inherits any pattern or the parent class of the model itself, completely transforming the business The code is decoupled;
2: In the event model, each listener (observer) needs to implement an interface of its own. That's right, look at our mouse events. The sub-table has click, double-click, move, etc. events, which respectively increase the flexibility of the code;
In any case, we use a bunch of small The white code implements an example of an event-driven model. Although it is of no practical use, it also explains the principle. In the next section, we will take a look at some slightly complex and seemingly useful code!
The above is the detailed content of Understand the JAVA event handling mechanism from scratch. For more information, please follow other related articles on the PHP Chinese website!