第一个全部自己实现的程序,做一下总结。
1.准备阶段
跟着别人写了个小小的swing项目,现在看来那个项目中,我收益最大的就是学到了多层结构的开发模式。即服务层——监听器层——数据库。当我越写到后面,类越多的时候,我就越能感觉到这模式的好处。
看图
2.需求分析
操作:这一步我其实是有点难去分析的,我没在网上找到一个系统去参考,找到了的也是ssm框架之类的实现,我不懂,还有两个确实有swing实现但是要钱…所以我折中了一下,看看他们的功能描述有哪些,还有看看他们的swing界面是怎么样的,根据这些来初步得知练习系统大概有什么功能。
反思:这一步对写程序我觉得挺重要的。这个系统我花了2/3的事件去写代码,然后花了1/3的时间去改代码。不是代码错了要改,而是最先开始的需求分析不明确,导致一些功能实现的云里雾里的。不只是功能,表的设计也会受到很大影响,到后面表一改,好多代码都要对应的改,不是难,而是会很麻烦很容易漏掉一些边角处没改。
3.表结构设计
4.界面原型
界面设计的话,由于已经有需求分析得出的结果了,就从登录界面一个个推出来,不难,但很麻烦。
第一步的设计我是在网上找了一些练习系统的例子,一般他们都会演示程序完成结果,就会有界面出来,根据他们的界面来设计自己的界面,这样会容易点。
画界面的话我分两种,简单一点的就自己写,技术达不到的就自己写一点,其他的用WindowBuilder一个个拖上去。WindowBuilder画swing界面挺好用的,可以百度教程。
画完原型后接下来就是功能模块的实现了,第一阶段的原型肯定是不完整的,其他的就留到实现功能的时候再慢慢补,看有什么缺漏或者需要删除的。
swing图我一开始最怕的就是表格JTable了,完全不懂它的运行格式,只是照搬别人的格式,写到最后的时候,才突然发现JTable是怎么运作的。
5.功能实现、实体类和DAO
功能实现就要回到开头的那个图了。
来捋一捋:
界面→事件监听器→服务层→DAO层→数据库,
来实例:
1.首先我们通过界面原型那步画了一个题目管理界面出来
2.现在我们来分析这个界面有什么功能需要实现。
(1)增加题目功能
(2)修改题目功能
(3)查看题目详情功能
(4)查找功能(查找功能又可以细分)
(4)根据题目编号查找题目功能
(5)根据知识点查找题目功能
(6)根据题目分数查找题目功能
(7)查找所有题目的功能
注意:规定教师只能对本学科的题目进行操作,所以查找功能隐含限制要加上“根据学科查找”,增加题目功能也是只能增加本学科的题目
仔细分析一下
前三个功能怎么样实现,增加、修改、查看可以在这个界面完成吗?我的做法是为这三个操作每个操作再新建一个界面。也即点击增加、修改、查找按钮会跳出对应的界面,在那个界面去进行操作。而查找功能的显示只需要在这个界面就可以完成。
3.开发思路:界面层→Service层
Service层是什么?看到第二步我们分析出来的功能了吗,界面需要的所有功能(一般情况下)我们都需要在Service层实现。Service层就是封装了界面功能的实现
创建一个service类,里面有很多个方法。
public class questionManageService {
//增加按钮,跳转到跳转到增加题目界面
public void add(){
//里面是具体的功能实现
}
//修改按钮,跳转到修改题目界面
public void update(Question question){
}
//详细按钮,跳转到题目详情界面
public void details(Question question){
}
//根据题目编号查找(其实还要加上学科限制)
public List<Question> getById(int id, String subject){
}
//根据知识点查找(加上学科限制)
public List<Question> getByPoint(String point, String subject){
}
//根据分数查找(加上学科限制)
public List<Question> getByScore(int score, String subject){
}
//查找全部,这里的查找全部即为按照学科查找
public List<Question> getBySubject(String subject){
}
}
注意查找功能隐含限制要加上“根据学科查找”
4.开发思路:Service层→DAO层
我们从上一步功能分析知道有个查找功能。那去哪里查找呢?易拉罐里有饮料,为了喝到里面的饮料,我们需要一根吸管。DAO层就是那根吸管,就像是连接java代码和数据库的一条通道
这个通道里有增、删、改、查四个小通道,Service层需要用到什么,就走(调用)什么通道。
5.开发思路:DAO层→数据库,实体
感觉有点自顶向下那味儿了
6.第五步后service层就算实现了。接下来是Listener层。这层是监听器层,封装了界面上所有按钮的监听器。来看下题目管理界面有什么按钮
增加按钮、修改按钮、详情按钮、查找按钮。在点击这些按钮之后系统需要作出对应的反应,怎么才能作出反应呢,就需要为这些按钮添加监听器,监听这些按钮是不是被点击了,点击之后我们要干什么。当然,我们可以在界面类那里直接就写监听器,但那样需要每个按钮实现一个监听器,会弄得代码很繁杂,不利于问题定位或者修改代码。所以我们专门分出一个类来作为该界面监听器。该界面所有的按钮只要加这一个监听器就行。
public class questionManageListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
//取得面板实例和事件源和老师学科
questionManageFrm f = questionManageFrm.instance;
Object b =e.getSource();
Teacher teacher = (Teacher)LoginFrm.instance.user;
//点击增加按钮
if(b == f.bAdd) new questionManageService().add();
//点击修改按钮
if(b == f.bUpdate) {
Question question = f.getSelectedQuestion();
new questionManageService().update(question);
}
//点击详细
if(b == f.bDetails){
Question question = f.getSelectedQuestion();
new questionManageService().details(question);
}
//点击查找按钮
if(b == f.bSearch){
String choice = (String)f.comboBox.getSelectedItem();
String s = f.textField.getText().trim();
//让“所有”查找放在空判断前面,因为“所有”查找时文本框就是空的
if("所有" == choice){
List<Question> questions = new questionManageService().getBySubject(teacher.subject);
f.updateData(questions);
return;
}
if(0 == s.length()){
JOptionPane.showMessageDialog(f, "输入不能为空");
return;
}
if("题目编号" == choice){
if(!GUIUtil.checkNumber("题目编号", f.textField))
return;
List<Question> questions = new questionManageService().getById(Integer.parseInt(s), teacher.subject);
f.updateData(questions);
}
if("知识点" == choice){
List<Question> questions = new questionManageService().getByPoint(s, teacher.subject);
f.updateData(questions);
}
if("分数" == choice){
if(!GUIUtil.checkNumber("分数", f.textField))
return;
List<Question> questions = new questionManageService().getByScore(Integer.parseInt(s), teacher.subject);
f.updateData(questions);
}
f.textField.setText("");
}
//点击复选框,当选择“所有”时,文本框清空且不可用
if(b == f.comboBox){
String choice = (String)f.comboBox.getSelectedItem();
if("所有" == choice) {
f.textField.setText("");
f.textField.setEnabled(false);
}
else f.textField.setEnabled(true);
}
}
}
7.许多人会分不清Service层、DAO层、Listener层
DAO层:直接跟数据库打交道,封装一条条基本的增删改查操作
Service层:封装界面所需的所有功能,跟DAO层打交道,把一条条增删改查操作组合,组合成为界面的一个个功能
Listene层:跟Service层打交道,跟界面打交道。监听界面的事件,并根据事件类型作出不同反应,这些反应就是调用Service层实现的。
6.遇到的问题
1.遇到最多的问题就是空指针问题,大多是由于程序设计的不周全所致,这是当时的一个记录
2.对于试卷题目表中题目太多,在写代码时不想全部写的问题。问题记录,这里用了反射
3.在考试时我使用了一个倒计时线程,线程结束时会自动提交。但是当我提前交卷时关掉界面时,线程并没有停止。所以我发现我当时忘了加个线程停止的步骤。网上查了方法,然后采用了标志位的去停止线程。这是网上查的方法