把之前的学生管理系统,改造成三层架构的形式
三层架构即:
视图层,通常用于与用户交互,收集用户输入的信息,展示信息
业务层,通常做业务逻辑处理
持久层,通常只做与数据增删改查相关的操作
对应的包结构就是
视图层 controller
业务层 service
持久层 dao
外加 domain 存放模型类、entry 程序入口、utils 工具类
先来entry写程序入口
顺便把这个管理系统升级成携带老师管理的信息管理系统
以学生管理系统为例,主要介绍,老师管理系统同学生管理系统一样实现
因为controller是用于与用户交互的
所以main方法调用StudentController对象的start方法,进入学生管理系统部分
public class InfoManagerEntry {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("--------欢迎来到信息管理系统--------");
System.out.println("请输入您的选择: 1.学生管理 2.老师管理 3.退出");
String choice = sc.next();
switch (choice) {
case "1":
//System.out.println("学生管理");
StudentController studentController = new StudentController();
studentController.start();
break;
case "2":
//System.out.println("老师管理");
new TeacherController().start();
break;
case "3":
System.out.println("感谢您的使用");
System.exit(0); // 退出当前运行的JVM虚拟机
break;
default:
System.out.println("您的输入有误 请重新输入");
break;
}
}
}
}
在domain中创建Student类
包含几个简单字段,并带有get/set方法,以及无参和有参构造方法
public class Student {
private String id; // 学号
private String name; // 姓名
private int age; // 年龄
private String birthday; // 生日
public Student() {
}
public Student(String id, String name, int age, String birthday) {
this.id = id;
this.name = name;
this.age = age;
this.birthday = birthday;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}
在StudentController中 编写方法start()实现学生管理系统的主界面输出
public void start() {
while (true) {
System.out.println("--------欢迎来到 <学生> 管理系统--------");
System.out.println("请输入您的选择: 1.添加学生 2.删除学生 3.修改学生 4.查看学生 5.退出");
String choice = sc.next();
switch (choice) {
case "1":
//System.out.println("添加学生");
addStudent();
break;
case "2":
//System.out.println("删除学生");
deleteStudent();
break;
case "3":
//System.out.println("修改学生");
updateStudent();
break;
case "4":
//System.out.println("查看学生");
showStudent();
break;
case "5":
System.out.println("感谢您的使用");
return;
default:
System.out.println("您的输入有误");
break;
}
}
}
分别编写各个功能调用的具体方法
添加学生功能
private void addStudent() {
// 接受用户输入信息
String id;
while (true) {
System.out.println("请输入学号:");
id = sc.next();
int i = studentService.findStudentIndexById(id);
if (i != -1) {
System.out.println("学号已被占用 请重新输入");
} else {
break;
}
}
Student stu = inputStudentInfo(id);
// 传递给业务层
boolean result = studentService.addStudent(stu);
// 控制台打印添加成功/添加失败
if (result) {
System.out.println("添加成功");
} else {
System.out.println("添加失败");
}
}
此处与之前版本的管理系统不同的是视图层把具体的操作数据的任务交给业务层,让业务层去找持久层完成数据的添加功能
视图层只负责把用户的输入提交给业务层,并把业务层的返回的结果输出给用户,完成与用户的交互
业务层对象StudentService studentService = new StudentService();
在StudentController的成员变量中声明
学生信息的添加功能需要先调用业务层的findStudentIndexById方法查找用户输入的学号是否已存在,该方法当存在用户输入的学号时,返回该条记录的索引,不存在则返回-1,因此可以用其判断学号是否被占用
在业务层中实现findStudentIndexById方法,调用持久层的getIndex方法查询索引并返回结果,目前的业务层负责的业务仅仅是传递信息
public int findStudentIndexById(String id) {
return studentDao.getIndex(id);
}
在持久层使用ArrayList类型的成员变量“list”存储对象,因此getIndex方法如下
public int getIndex(String id) {
int index = -1;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getId().equals(id)) {
index = i;
break;
}
}
return index;
}
数据逐层return到Controller,便可以返回值判断是否继续添加输入信息
当用户输入一个未被占用的学号时,StudentController的addStudent方法继续执行,为了方便,我把用户输入的数据封装Student对象的部分提取成一个方法inputStudentInfo
private Student inputStudentInfo(String id) {
System.out.println("请输入姓名:");
String name = sc.next();
System.out.println("请输入年龄:");
String age = sc.next();
System.out.println("请输入生日:");
String birthday = sc.next();
return new Student(id, name, age, birthday);
}
之后StudentController的addStudent方法会调用StudentService的addStudent传递Student实例给业务层,让业务层完成添加工作,并返回一个boolean类型结果表示是否添加成功
在业务层的addStudent方法中,调用持久层的addStudent方法,完成数据添加
public boolean addStudent(Student stu) {
// 传递给持久层 返回结果给视图层
return studentDao.addStudent(stu);
}
持久层则直接调用ArrayList的add方法向“list”对象中添加Student对象
public boolean addStudent(Student stu) {
return list.add(stu);
}
至此,添加学生的功能就实现完成了
查看学生功能
对视图层来说,查看学生功能需要从业务层获取到所有学生的集合,然后遍历集合逐一打印到控制台。并且当集合为空的时候,给用户打印额外的提示信息
private void showStudent() {
// 从业务层获取所有学生的集合
ArrayList<Student> students = studentService.findAllStudent();
if (students.size() == 0) {
System.out.println("查无信息 请添加后重试");
return;
}
// 打印表头
System.out.println("学号 姓名 年龄 生日");
// 遍历集合并打印元素
for (Student stu : students) {
System.out.println(stu.getId() + " "
+ stu.getName() + " "
+ stu.getAge() + " "
+ stu.getBirthday());
}
}
业务层找持久层要集合对象,即:在业务层的findAllStudent方法中调用持久层的findAllStudent方法获取集合对象
public ArrayList<Student> findAllStudent() {
return studentDao.findAllStudent();
}
在持久层中,直接返回集合对象
public ArrayList<Student> findAllStudent() {
return list;
}
逐层返回数据到视图层,视图层便可向用户打印输出
至此,查看学生的功能就实现完成了
删除学生功能
对视图层来说,删除学生需要判断用户输入的学号是否存在,若存在则删除,不存在则提示用户
其中判断用户输入的学号是否存在的逻辑,基本同添加学生功能的判断用户输入的学号是否存在的逻辑一致。调用的都是同一个方法获取索引,然后再根据索引判断。不同的只是判断的条件不一致。接下来具体分享一下调用的业务层的deleteStudent方法
private void deleteStudent() {
System.out.println("请输入学号");
String id = sc.next();
int index = studentService.findStudentIndexById(id);
if (index == -1) {
System.out.println("学号" + id + " 不正确 请重新输入");
} else {
studentService.deleteStudent(id);
System.out.println("删除成功");
}
}
删除的业务同样是交由业务层处理,所以调用业务层的deleteStudent方法。
该方法调用持久层的deleteStudentById方法根据id删除元素,剩下操作数据的任务交给持久层完成。
public void deleteStudent(String id) {
studentDao.deleteStudentById(id);
}
在持久层中,调用getIndex方法获取到要删除的对象的索引,根据索引直接在集合中remove元素。
public void deleteStudentById(String id) {
int index = getIndex(id);
list.remove(index);
}
至此,删除功能实现完成。
更新学生功能
更新功能和上述的添加和删除功能相似度很高,就不详细写了。
小结
三层就是,视图层处理用户交互,即输入输出操作,之后把工作交给业务层完成。之后业务层把操作数据的具体工作交给持久层完成。