1、JavaBeans
一种软件组件结构,扩展了Java语言的功能,能够构造可重用的软件组件。
2.Bean属性
用户访问属性的方法被限制为:get方法,命名为get<PropertyName>(),不带参数,返回一个与属性类型一致的基本数据类型值或对象,注意声明为public的。例如:
public String getMessage(){}
public int getXCoordinate(){}
对于一个boolean类型的属性,get方法命名为is<PropertyName>(),返回一个boolean类型的值,声明为public的,例如:
public boolean isCentered(){}
set方法应该命名为set<PropertyName>(dataType p),带一个与属性类型相同的参数,返回值是void,声明为public,例如:
public void setMessage(String s){}
public void setXCoordinate(int x){}
注意JavaBean组件中的属性,不一定必须是一个数据域,比如:
public int getMessageLength(){
return message.length();
}
6、监听器组件
对于一个事件,监听器组件必须实现事件监听器接口,如果一个监听器组件的对象未注册为源对象的监听器,则它就不能接受来自源组件的事件通知。一个监听器可以实现任意多个监听器接口,以便监听多种类型的事件。例如下面代码:
3.Java事件模型
Java时间模型由事件对象、源对象和事件监听器对象组成。
事件是程序发生某些事情的信号。事件对象包含描述事件的信息。源对象表示事件初始发生时的位置。一个关注事件的对象接受事件,这样的对象称为监听器。一个对象要能接受事件,必须对该对象注册监听器。Java事件模型称为事件委托模型,因为源对象将事件处理任务委托给了监听器。
4、事件对象是使用事件类来创建的,如ActionEvent,所有事件类都是EventObject的子类,包含与具体事件类型相关的数据值和方法。每个事件类与一个事件监听器接口相关联,这种接口定义为一个或多个处理器的方法。事件监听器接口都是EventListener的子接口。处理器由监听器组件实现。当检测到事件发生时,源组件调用监听器的处理器。事件类和与它的监听器接口是相互依存的,所以称其为事件组或事件对。事件XEvent的监听器必须命名为XListener。
5.原组件
监听器接口-->处理器方法-->监听器组件(处理器)
源组件包含检测代码,用于检测引发事件的外部或内部动作,当检测到动作时,源组件调用监听器所定义的事件处理器向监听器触发事件。源组件包含注册和注销监听器的方法。源组件--检测--事件-->监听器的事件处理器
6.监听器组件
对于一个事件,监听器组件必须实现事件监听器接口,如果一个监听器组件的对象未注册为源组件的监听器,则它就不能接受来自源组件的事件通知。一个监听器可以实现任意多个监听器接口,以便监听多种类型的事件。例如下面代码:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class TestSourceListener {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new JFrame("TestSourceListener");
JButton jbt = new JButton("OK");
frame.add(jbt);
frame.setSize(200, 200);
frame.setVisible(true);
MyListener listener = new MyListener();
jbt.addActionListener(listener);
}
}
class MyListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("I will process it");
}
}
JButton jbt = new Jbutton("OK");是创建一个源对象。
MyListener listener = new MyListener();是创建一个监听器对象
jbt.addActionListener(listener);用源对象对监听器进行注册
7、创建自定义源组件
源组件必须有适当的注册与注销方法,用来添加和删除监听器。事件可以被单点传送,也可以被多点传送。添加一个单点传送监听器的命名方式为
public void add<Event>Listener(<Event>Listener l) throws TooMangListenersException;
添加多点传送监听器方法为:
public void add<Event>Listener(<Event>Listener l)
删除一个监听器的命名方式为:
public void remove<Event>Listener(<Event>Listener l);
源组件包含特定的代码,可以创建事件对象,并且可以调用事件监听器接口中的方法将事件对象传递给监听器组件。可以调用标准的的Java事件类来创建事件对象,也可以自定义事件类。
例如代码:
StudentsWithActionEvent是一个包含了事件处理功能的Java Bean,其中,students是属性,enrollmentCap也是属性,actionListenerList表示了监听器接口向量,public void addStudent方法 和 public String[] getStudents方法 以及 public int getNumberOfStudents方法,public int getEnrollmentCap方法,public void setEnrollmentCap方法 都是经典的java bean规范的方法声明形式,而public synchronized void addActionListener(ActionListener listener)和将具体实现的监听器对象向上抽象为ActionListener接口传入内部定义的监听器数组属性当中,实现了注册功能;removeActionListener则保持了监听器的注销功能,processEvent方法是源组件自己触发事件事件的途径,它通过遍历监控器数组逐个调用监控器对象的actionPerformed(e)方法实现对事件的处理。注意在执行actionPerformed时,将自身传进去了。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
public class StudentsWithActionEvent {
private ArrayList<String> students = new ArrayList<String>();
private int enrollmentCap = 10;
private ArrayList<ActionListener> actionListenerList;
public StudentsWithActionEvent(){
}
public void addStudent(String name) {
students.add(name);
if (students.size() > enrollmentCap){
processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));
}
}
public String[] getStudents() {
return (String[])students.toArray();
}
public int getNumberofStudents() {
return students.size();
}
public int getEnrollmentCap() {
return enrollmentCap;
}
public void setEnrollmentCap(int enrollmentCap) {
this.enrollmentCap = enrollmentCap;
}
public synchronized void addActionListener(ActionListener listener){
if (actionListenerList == null){
actionListenerList = new ArrayList<ActionListener>(2);
}
if (!actionListenerList.contains(listener)){
actionListenerList.add(listener);
}
}
public synchronized void removeActionListener(ActionListener listener){
if (actionListenerList != null && actionListenerList.contains(listener)){
actionListenerList.remove(listener);
}
}
private void processEvent(ActionEvent e){
ArrayList list;
synchronized (this) {
if (actionListenerList == null)
return ;
list = (ArrayList)actionListenerList.clone();
}
for (int i = 0; i < list.size();i++){
ActionListener listener = (ActionListener)list.get(i);
listener.actionPerformed(e);
}
}
}
StudentsWithActionEvent类负责存储班级学生姓名,当学生数目超过限制时, StudentsWithActionEvent对象激发ActionEvent事件,并调用监听器的 actionPerformed方法通知监听器。源组件负责注册监听器、创建事件、调用在监听器接口中定义的方法。
测试代码:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestStudentsWithActionEvent {
StudentsWithActionEvent studentsWithActionEvent = new StudentsWithActionEvent();
public TestStudentsWithActionEvent() {
// TODO Auto-generated constructor stu
studentsWithActionEvent.setEnrollmentCap(2);
ActionListener listener = new Listener();
studentsWithActionEvent.addActionListener(listener);
studentsWithActionEvent.addStudent("John");
studentsWithActionEvent.addStudent("Jim");
studentsWithActionEvent.addStudent("Tim");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new TestStudentsWithActionEvent();
}
}
class Listener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("EnrollmentCap cap exceeded");
}
}
程序运行显示nrollmentCap cap exceeded
import java.util.EventObject;
public class EnrollmentEvent extends EventObject {
private int numberOfStudents;
private int enrollmentCap;
public EnrollmentEvent(Object source, int numberOfStudents, int enrollmentCap) {
super(source);
this.numberOfStudents = numberOfStudents;
this.enrollmentCap = enrollmentCap;
}
public int getNumberOfStudents() {
return numberOfStudents;
}
public int getEnrollmentCap() {
return enrollmentCap;
}
}
import java.util.EventListener;
public interface EnrollmentListener extends EventListener {
public void enrollmentExceed(EnrollmentEvent e);//监听器接口实现的方法:类似于actionPerformed的事件处理器
}
运用自定义的事件类和事件监听器接口的程序:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
public class StudentsWithEnrollmentEvent {
private ArrayList<String> students = new ArrayList<String>();
private int enrollmentCap = 10;
private ArrayList<EnrollmentListener> enrollmentListenerList;
public StudentsWithEnrollmentEvent(){
}
public void addStudent(String name) {
students.add(name);
if (students.size() > enrollmentCap){
processEvent(new EnrollmentEvent(this, getNumberofStudents(), getEnrollmentCap()));//学生数目超限,触发事件,注意这里将源组件的属性都通过构造函数
//传递给了EnrollmentEvent,并将自己的引用传给了它
}
}
public String[] getStudents() {
return (String[])students.toArray();
}
public int getNumberofStudents() {
return students.size();
}
public int getEnrollmentCap() {
return enrollmentCap;
}
public void setEnrollmentCap(int enrollmentCap) {
this.enrollmentCap = enrollmentCap;
}
public synchronized void addEnrollmentListener(EnrollmentListener listener){
if (enrollmentListenerList == null){
enrollmentListenerList = new ArrayList<EnrollmentListener>(2);//源组件包含了注册监听器的方法
}
if (!enrollmentListenerList.contains(listener)){
enrollmentListenerList.add(listener);
}
}
public synchronized void removeEnrollmentListener(EnrollmentListener listener){//以及注销监听器的方法
if (enrollmentListenerList != null && enrollmentListenerList.contains(listener)){
enrollmentListenerList.remove(listener);
}
}
private void processEvent(EnrollmentEvent e){//事件是源组件自己触发的,到目前为止还没有传递给监听器去处理
ArrayList list;
synchronized (this) {
if (enrollmentListenerList == null)
return ;
list = (ArrayList)enrollmentListenerList.clone();//clone整个监听器数组???why???
}
for (int i = 0; i < list.size();i++){
EnrollmentListener listener = (EnrollmentListener)list.get(i);
listener.enrollmentExceed(e);//直接调用监听器的处理方法,传递了一个EnrollmentEvent对象,这个对象其实封装了几乎和源组件一样的
//属性和方法,还super了EventObject构造方法中的第一个Object参数,why???要这个参数?参数传递了源组件
}
}
}
测试代码:
public class TestStudentsEnrollmentEvent {
StudentsWithEnrollmentEvent studentsWithEnrollmentEvent = new StudentsWithEnrollmentEvent();
public TestStudentsEnrollmentEvent() {
studentsWithEnrollmentEvent.setEnrollmentCap(2);
EnrollmentListener listener = new NewListener();
studentsWithEnrollmentEvent.addEnrollmentListener(listener);
studentsWithEnrollmentEvent.addStudent("John");
studentsWithEnrollmentEvent.addStudent("Jim");
studentsWithEnrollmentEvent.addStudent("Tim");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new TestStudentsEnrollmentEvent();
}
}
class NewListener implements EnrollmentListener {
@Override
public void enrollmentExceed(EnrollmentEvent e) {
// TODO Auto-generated method stub
System.out.println(e.getNumberOfStudents() + " enrolled" + "and the enrollmentcap is " + e.getEnrollmentCap());
}
}
输出:3 enrolledand the enrollmentcap is 2