事件模型三(使用匿名内部类实现事件处理)

        

目录

使用匿名内部类实现 MouseEvent 事件

分层开发实现事件—服务层之父接口 UserService

分层开发实现事件—服务层之登录按钮服务层

分层开发实现事件—服务层之退出按钮服务层

分层开发实现事件—服务层之清空文本框服务层

分层开发实现事件—服务层之工厂类

分层开发实现事件—监听层之登录按钮监听类

分层开发实现事件—监听层之退出按钮监听类

分层开发实现事件—监听层之清空文本框监听类

分层开发实现事件—视图层之窗口类


        在内部类中还有一种特殊的类,就是匿名内部类,那么使用匿名内部类会发现代码精简 程度更高。首先我们先回忆一下匿名内部类的特性:

  1. 匿名类是指没有指定名称的类。
  2. 匿名类最大的用途是编写事件处理程序。
  3. 匿名类的实质其实就是一个内部类,只是没有名称而已。

使用匿名内部类实现 MouseEvent 事件

package com.gui;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class LoginFrame extends JFrame {
    private JPanel pnlMain;
    //标签控件
    private JLabel lblTitle;
    private JLabel lblUserName;
    private JLabel lblUserPwd;
    //输入用户名的文本框控件
    private JTextField txtUserName;
    //输入密码的密码框控件
    private JPasswordField pwdUserPwd;
    //登录和退出按钮控件
    private JButton btnLogin;
    private JButton btnQuit;

    public LoginFrame() {
        //实例化各种容器和控件
        pnlMain = new JPanel(null);
        lblTitle = new JLabel("用户登录");
        lblUserName = new JLabel("用户姓名:");
        lblUserPwd = new JLabel("用户密码:");
        txtUserName = new JTextField();
        pwdUserPwd = new JPasswordField();
        btnLogin = new JButton("登录");
        btnQuit = new JButton("退出");
        init();
    }
    //该方法对窗口做初始化
    private void init() {
        // 设置窗口属性
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("登录窗口");
        this.setSize(300, 220);
        this.setResizable(false);
        /*
         * 设置各个控件的位置和坐标
         * setBounds 方法的前两个参数为控件的左上角坐标,后两个参数为控件的宽和高
         */
        lblTitle.setBounds(100, 10, 100, 30);
        lblUserName.setBounds(20, 60, 75, 25);
        lblUserPwd.setBounds(20, 100, 75, 25);
        txtUserName.setBounds(100, 60, 120, 25);
        pwdUserPwd.setBounds(100, 100, 120, 25);
        btnLogin.setBounds(50, 140, 75, 25);
        btnQuit.setBounds(150, 140, 75, 25);
        // 在用户姓名的文本框中添加默认文本
        txtUserName.setText("请输入用户姓名");
        // 在用户姓名的文本框上添加鼠标事件:使用匿名内部类
        txtUserName.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                // 将登陆界面中的用户姓名文本框中的文本清除
                txtUserName.setText("");
            }
        });
        //将所有控件压在容器上
        pnlMain.add(lblTitle);
        pnlMain.add(lblUserName);
        pnlMain.add(lblUserPwd);
        pnlMain.add(txtUserName);
        pnlMain.add(pwdUserPwd);
        pnlMain.add(btnLogin);
        pnlMain.add(btnQuit);
        this.add(pnlMain);
        this.setVisible(true);
    }
    //让鼠标监听类继承适配器后,只需要重写我们需要的方法即可
    class LoginFrame_txtUserName_MouseListener extends MouseAdapter {
        @Override
        public void mouseClicked(MouseEvent e) {
            txtUserName.setText("");
        }
    }
}

使用外部类(自定义的一个独立于窗口类的监听实现类)实现事件。

使用内部类实现事件。

内部类配合使用适配器实现事件。

匿名内部类实现事件。

让窗口类实现事件监听接口,使其即为窗口又为事件监听类。

        但是这么多种事件处理的方式,我们究竟该如何取舍呢?那是否是代码越少,质量越高 呢?其实我们完成代码不是以代码的多少进行取舍,而是要综合考虑代码的可维护性、可重 用性、负载问题等等。像后边四种方式代码耦合性高,这样如果需要更改业务逻辑或是界面 显示逻辑时,整个类就要修改,而且代码很难重用,尤其是匿名内部类(因为每使用一次就 重新产生一个新的类),对于并且窗口对象负载过重(既要负责显示、又要监听事件、还要 处理事件,相当于 3 个人的工作交给 1 个人完成)。所以综合考虑比较合适的还是第一种方 式。但是第一种仍然可以继续优化,因为它在监听类中完成了我们需要做的业务。这样监听 类功能不清,到底是做监听还是做业务?

        综上所述,按照我们以前所学过得 OOP 编程思想,我们应该把这段代码分:视图层(窗 口界面,它只负责如何显示)、监听层(实现某个 Listener 的类,它只负责监听)、服务层 (只负责完成业务逻辑的实现),那么实现结构为:窗口中对事件源添加监听,在监听类中 的具体事件方法中调用服务层完成业务。

        接下来我们使用这种模式完成一个用户登录按钮功能实现。首先定义一个用户模块下的最终父接口 UserService

分层开发实现事件—服务层之父接口 UserService

package com.gui;

import java.awt.Window;
import java.util.EventObject;

public interface UserService {
    void execute(EventObject e,Window w);

}

        该接口是用户模块下所有 Service 类的最终父接口。接下来定义三个服务层(登录按钮 服务层、退出按钮服务层、清空文本框服务层)的实现子类。

分层开发实现事件—服务层之登录按钮服务层

package com.gui;

import java.awt.Window;
import java.util.EventObject;
import javax.swing.JOptionPane;

/**
 * 登陆功能服务层.
 */
public class LoginService implements UserService {

    @Override
    public void execute(EventObject e, Window w) {
        LoginFrame lf = (LoginFrame)w;
        String userName = lf.getTxtUserName().getText().trim();
        //获得用户密码的密码框对象的文本内容
        String userPwd = new String(lf.getPwdUserPwd().getPassword()).trim();
        //验证用户账号是否填写
        if(userName.equals("")) {
            JOptionPane.showMessageDialog(null, "请输入用户姓名", "警告",
                    JOptionPane.WARNING_MESSAGE);
            return;
        }
        if(userName.equals("zhangsan") && userPwd.equals("sxt")) {
            /*
             * 弹出对话框,第 1 个参数为窗口,所以可以传 null,
             * 第 2 个参数为ᨀ示文本,第 3 个参数为标题信息,第 4 个参数为样式
             */
            JOptionPane.showMessageDialog(null, "欢迎您:"+userName, "ᨀ示",
                    JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        JOptionPane.showMessageDialog(null, "用户姓名或密码错误", "错误",
                JOptionPane.ERROR_MESSAGE);
    }
}

分层开发实现事件—服务层之退出按钮服务层

package com.gui;

import java.awt.Window;
import java.util.EventObject;

/**
 * 退出功能服务层.
 */
public class QuitService implements UserService {
    @Override
    public void execute(EventObject e, Window w) {
        w.dispose();
    }
}

分层开发实现事件—服务层之清空文本框服务层

package com.gui;

import java.awt.Window;
import java.util.EventObject;

/**
 * 清空文本框服务层.
 */
public class ResetUserNameService implements UserService {
    @Override
    public void execute(EventObject e, Window w) {
        LoginFrame lf = (LoginFrame)w;
        lf.getTxtUserName().setText("");
    }
}

        接下来我们需要定义一个工厂类,获得具体服务层的对象

分层开发实现事件—服务层之工厂类

package com.gui;

/**
 * 用户模块服务层工厂类.
 */
public abstract class UserServiceFactory {
    /**
     * 获得登陆功能业务逻辑对象.
     */
     public static UserService createLoginService() {
        return new LoginService();
     }
     /**
     * 获得退出功能业务逻辑对象.
     */
    public static UserService createQuitService() {
        return new QuitService();
    }
    /**
     * 获得清空文本框功能业务逻辑对象.
     */
    public static UserService createResetUserNameService() {
        return new ResetUserNameService();
    }
}

        然后,定义 3 个监听类(分别对应 3 个事件监听)

分层开发实现事件—监听层之登录按钮监听类

package com.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginFrame_btnLogin_ActionListener implements ActionListener {
    private LoginFrame lf;
    private UserService service;
    public LoginFrame_btnLogin_ActionListener(LoginFrame lf) {
        this.lf = lf;
        service = UserServiceFactory.createLoginService();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        service.execute(e, lf);
    }
}

分层开发实现事件—监听层之退出按钮监听类

package com.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginFrame_btnQuit_ActionListener implements ActionListener {
    private LoginFrame lf;
    private UserService service;
    public LoginFrame_btnQuit_ActionListener(LoginFrame lf) {
        this.lf = lf;
        service = UserServiceFactory.createQuitService();
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        service.execute(e, lf);
    }
}

分层开发实现事件—监听层之清空文本框监听类

package com.gui;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

/**
 * 清空文本框功能监听类.
 */
public class LoginFrame_txtUserName_MouseListener extends MouseAdapter {
    private LoginFrame lf;
    private UserService service;
    public LoginFrame_txtUserName_MouseListener(LoginFrame lf) {
        this.lf = lf;
        service = UserServiceFactory.createResetUserNameService();
    }
    @Override
    public void mouseClicked(MouseEvent e) {
        service.execute(e, lf);
    }
}

        最后,我们定义一个窗口类

分层开发实现事件—视图层之窗口类

package com.gui;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class LoginFrame extends JFrame {
    private JPanel pnlMain;
    //标签控件
    private JLabel lblTitle;
    private JLabel lblUserName;
    private JLabel lblUserPwd;
    //输入用户名的文本框控件
    private JTextField txtUserName;
    //输入密码的密码框控件
    private JPasswordField pwdUserPwd;
    //登录和退出按钮控件
    private JButton btnLogin;
    private JButton btnQuit;

    public LoginFrame() {
        //实例化各种容器和控件
        pnlMain = new JPanel(null);
        lblTitle = new JLabel("用户登录");
        lblUserName = new JLabel("用户姓名:");
        lblUserPwd = new JLabel("用户密码:");
        txtUserName = new JTextField();
        pwdUserPwd = new JPasswordField();
        btnLogin = new JButton("登录");
        btnQuit = new JButton("退出");
        init();
    }
    //对文本框对象和密码框对象添加 get 方法
    public JTextField getTxtUserName() {
        return txtUserName;
    }
    public JPasswordField getPwdUserPwd() {
        return pwdUserPwd;
    }
    //该方法对窗口做初始化
    private void init() {
        // 设置窗口属性
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("登录窗口");
        this.setSize(300, 220);
        this.setResizable(false);
        /*
         * 设置各个控件的位置和坐标
         * setBounds 方法的前两个参数为控件的左上角坐标,后两个参数为控件的宽和高
         */
        lblTitle.setBounds(100, 10, 100, 30);
        lblUserName.setBounds(20, 60, 75, 25);
        lblUserPwd.setBounds(20, 100, 75, 25);
        txtUserName.setBounds(100, 60, 120, 25);
        pwdUserPwd.setBounds(100, 100, 120, 25);
        btnLogin.setBounds(50, 140, 75, 25);
        btnQuit.setBounds(150, 140, 75, 25);
        /*
         * 在退出按钮上添加按钮按下监听对象,
         * 并在实例化监听对象中传入当前窗口对象本身
         */
        btnQuit.addActionListener(
                new LoginFrame_btnQuit_ActionListener(this));
        /*
         * 在登录按钮上添加按钮按下监听对象,
         * 并在实例化监听对象中传入当前窗口对象本身
         */
        btnLogin.addActionListener(
                new LoginFrame_btnLogin_ActionListener(this));
        //在用户姓名的文本框中添加默认文本
        txtUserName.setText("请输入用户姓名");
        //在用户姓名的文本框上添加鼠标事件
        txtUserName.addMouseListener(
                new LoginFrame_txtUserName_MouseListener(this));
        //将所有控件压在容器上
        pnlMain.add(lblTitle);
        pnlMain.add(lblUserName);
        pnlMain.add(lblUserPwd);
        pnlMain.add(txtUserName);
        pnlMain.add(pwdUserPwd);
        pnlMain.add(btnLogin);
        pnlMain.add(btnQuit);
        this.add(pnlMain);
        this.setVisible(true);
    }
}

        通过分 层开发的思想实现了“窗口中对事件源添加监听,在监听类中的具体事件方法中调用服务层 完成业务”的逻辑,使代码逻辑更加清晰。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值