单一职责原则
1.案例
某基于Java的C/S的“登录功能”通过如下登录类(login)实现,图中省略了属性,类中方法说明如下:init()初始化按钮、文本框等界面控件;display()用于向界面容器中添加界面控件并显示窗口;validate()供登录按钮的事件处理进行调用,用于调用和数据库有关的方法完成登录处理,成功登录就进入主界面,否则给出错误提示;getConnection()是获取数据库连接对象Connection用于连接数据库;findUser()用于根据用户名和密码进行验证数据库是否存在该用户,并供validate()方法调用;main为主函数入口。
2.分析
由于该类承担了太多的职责,无论是对界面修改还是对数据库的修改都需要修改该类,因此该类难以维护。现在根据单一职责将其拆分如下几个类:
图中涉及到UML的知识,在这里就不多叙述,感兴趣的可以去看看。
3.实现
由于书中并没有实现,我自己也是Java新手吧,就想着来实现一道,代码中存在的不足,还请多多指教。
3.1DBUtil类的实现如下:
package SRP; import java.sql.*; public class DBUtil { /* * 负责数据库的连接,该类可以提供多个数据库操作类重用 * */ private Connection connection=null; private String urlDb;//数据库 private String user;//用户名 private String password;//密码 public DBUtil() { } Connection getConnection() { urlDb="jdbc:mysql://localhost:3305/java";//java是数据库名字 user="root"; password="XXX"; try { Class.forName("com.mysql.jdbc.Driver"); }catch (ClassNotFoundException e) { e.printStackTrace(); } try { connection=DriverManager.getConnection(urlDb, user, password);//连接数据库 }catch (SQLException e) { e.printStackTrace(); } return connection; } }
3.2LoginForm类实现如下:
package SRP; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JTextField; /* * *负责显示界面,因此只包含与界面有关的方法和事件处理方法 * */ public class LoginForm extends JFrame { private UserDAO dao; private JButton btnLogin=null; private JButton btnClear=null; private JTextField txtId=null; private JTextField txtPwd=null; private JLabel lblId=null; private JLabel lblPwd=null; public LoginForm() { setVisible(true); } public void initControls()//初始化控件 { btnLogin=new JButton("登录"); btnClear=new JButton("清空"); lblId=new JLabel("账号:"); lblPwd=new JLabel("密码:"); txtId=new JTextField(); txtPwd=new JTextField(); lblId.setBounds(80,50,40,20); lblPwd.setBounds(80,80,40,20); txtId.setBounds(130,50,100,20); txtPwd.setBounds(130,80,100,20); btnLogin.setBounds(80,110,70,20); btnClear.setBounds(160,110,70,20); //添加事件 btnLogin.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Validate(); } }); btnClear.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { txtId.setText(""); txtPwd.setText(""); } }); } public void showControls()//面板添加控件 { Container container=this.getContentPane(); setTitle("登录"); setLayout(null);//绝对布局 setSize(300,250); setVisible(true); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//设置关闭窗口默认方式 setBackground(Color.yellow); container.add(btnClear); container.add(btnLogin); container.add(lblId); container.add(lblPwd); container.add(txtId); container.add(txtPwd); } public void Validate()//验证用户 此处提醒Java小白(我自己)JFrame有个validate()函数,如果不自己重新正确命名,就会有意想不到的效果(嘿嘿嘿)。 { dao=new UserDAO(); String userId=txtId.getText().trim(); String password=txtPwd.getText().trim(); if(dao.findUser(userId, password)==true) { JOptionPane.showMessageDialog(null, "登录成功"); } else { JOptionPane.showMessageDialog(null, "登录失败"); } } }
3.3UserDAO类的实现如下:
package SRP; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class UserDAO { /* * 负责数据库的增删改查操作,丰庄路对用户表的全部操作代码 * */ private DBUtil db=null; public UserDAO() { } boolean findUser(String userId,String userPwd) { db=new DBUtil(); Connection connection=db.getConnection(); try { Statement sql=connection.createStatement();//获取执行sql的对象 ResultSet resultSet=sql.executeQuery("select * from user where name='"+userId+"' and password='"+userPwd+"'"); resultSet.last(); if(resultSet.getRow()<1) return false;//未找到 else return true; }catch(Exception e) { e.printStackTrace(); return false; } } }
3.4MainClass类实现如下:
package SRP; public class MainClass { public MainClass() { LoginForm form=new LoginForm(); form.initControls(); form.showControls(); } public static void main(String[] args) { // TODO Auto-generated method stub new MainClass();//程序入口 } }
声明:我参考的书是清华大学出版社的《设计模式》,由刘伟主编。