[疯狂Java]监听器的实现:内部(闭包)、反射、外部

1. 用内部类和闭包实现监听器:

    1) 之前讲的所有形式都是内部类实现监听器,即在类内部定义一个监听器;

    2) 但最常用的还是闭包了,即匿名内部类和Lambda表达式:

         i. 因为监听器通常都是临时使用的代码,往往不会在其它地方被复用;

         ii. 即使要复用肯定会被抽象到业务逻辑层面单独编写;

         iii. 因此通常为了方便会用匿名内部类或者Lambda表达式来实现监听器;

     3) 匿名内部类示例:

Frame f = new Frame("Test");
f.addWindowListener(new WindowAdapter() {

	@Override
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		// super.windowClosing(e);
		System.exit(0);
	}
	
});
!!由于WindowAdapter不只有一个方法(7个),因此不是函数式接口,不能使用Lambda表达式;

    4) Lambda表达式:只适用于函数是接口,注意!函数式监听器接口(ActionListener等)没有对应的适配器,因为只有一个方法,没必要提供适配器

Button btn = new Button("button");
btn.addActionListener(e -> System.out.println(e.getActionCommand()));

2. 反射:

    1) 反射一词来自MFC,即组件自己监听自己的意思,这种组件就是智能组件,这种反射就叫做组件反射;

    2) 当然在Java中就是让类自己来监听自己的组件,这就叫类反射,当然MFC式的组件反射也可以实现;

    3) 反射的示例:类反射和组件反射

public class AwtTest extends WindowAdapter { // 类自己监听自己的组件

	Frame f = new Frame("WindowAdapter Test");

	class MyButton extends Button implements ActionListener { // 组件自己监听自己

		public MyButton(String label) throws HeadlessException {
			super(label);
			// TODO Auto-generated constructor stub
			this.addActionListener(this); // 组件自反射
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			System.out.println("Button pushed!");
		}
		
	}
	
	@Override
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		System.exit(0);
	}

	public void init() {
		f.addWindowListener(this); // 类自反射
		f.add(new MyButton("button"));
		f.pack();
		f.setVisible(true);
	}

	public static void main(String[] args) {
		new AwtTest().init();
	}

}
!像这样的按钮只要new出来随便用就行了,它产生的事件都由它自己来处理(自定义按钮);

!!注意this的应用是实现反射的关键;

    4) 反射的缺点:

         i. 通常组件、GUI类(用于显示界面的类,上面的类就是GUI类,PS:其实组件也是GUI类,用于显示组件本身)就只负责显示界面;

         ii. 监听、处理事件应该放到另一个模块来处理,因为这符合MVC设计思想;

         iii. 因此反射的缺点就是程序结构混乱,模块耦合度高;


3. 外部:

    1) 将监听器单独定义成外部类,然后GUI界面调用它;

    2) 最大的缺点:

         i. 监听器通常属于特定的GUI界面,定义在外部降低了程序的内聚性;

         ii. 外部类不能自由访问GUI界面类中的数据(组件),编程不简洁;

    3) 示例:监听邮件发送按钮的监听器定义在外部

         i. 监听器:

public class MailerListener implements ActionListener {
	private TextField mailAdress;
	
	public MailerListener() {}
	public MailerListener(TextField mailAdress) {
		this.mailAdress = mailAdress;
	}
	
	public TextField getMailAdress() {
		return mailAdress;
	}
	public void setMailAdress(TextField mailAdress) {
		this.mailAdress = mailAdress;
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		System.out.println("sending mail to '" + mailAdress.getText() + ".'\n");
	}
	
}
         ii. GUI:

public class AwtTest extends WindowAdapter { // 类自己监听自己的组件

	@Override
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		// super.windowClosing(e);
		System.exit(0);
	}
	
	public void init() {
		Frame f = new Frame("Sending Mail Test");
		TextField tf = new TextField(40);
		Button btn = new Button("send");
		
		f.addWindowListener(this);
		btn.addActionListener(new MailerListener(tf));
		
		f.add(tf);
		f.add(btn, BorderLayout.SOUTH);
		
		f.pack();
		f.setVisible(true);
	}
	
	public static void main(String[] args) {
		new AwtTest().init();
	}

}
!!可以看到监听器和GUI之间存在数据的共享,这加大了模块之间的耦合度,这无疑是对程序健壮性的一种危害!!要慎重使用;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值