文章目录
前言
提前祝大家中秋快乐了呀,时隔多日,我终于开始了 Java 基础 的第三个练手案例。至于为什么这么久才对这个练手案例动刀,说多了都是泪,这段时间新生开学,狗子我还调了宿舍,在搬宿舍的同时,一度被穿着蓝色军训服的大一新生围城 (# ̄~ ̄#)(师兄师姐你们怎么不吃饭)
好了不瞎扯了,后续也要加大力度了,否则被大一的师弟师妹们卷下去就很丢脸。
这次的是基于 Java基础 的第三个练手案例,和前两个一样,依旧是来自于 尚硅谷 的案例,真香 ~ 。在下文中将会对其基于我自己的理解,结合尚硅谷那边的解说逐一介绍案例中的过程和细节,文章可能会有点长部分源码就不放出来了。前两个案例的文章有兴趣的小伙伴可以自行跳转去查看呀!
噢对了,从这边文章开始狗子我的昵称便更改了,并且以后都是这个昵称。至于为什么呢?嗯嗯嗯……毕竟女朋友喜欢这个外号,<( ̄︶ ̄)>。开干!
一、前期准备
在开始搞事情之前得先准备好下面这些东西,其中 JDK 和 IDE 不一定需要统一,这只是狗子我使用的版本而已。准备好之后带上我们的脑子就可以开搞啦
- 编程语言 : Java
- 运行环境 : JDK1.8
- IDE : IDEA 2020
- 储备知识 : Java基础
二、整体架构介绍
在这次案例中和第二次案例一样,同样使用到了 MVC框架 ,将业务层和视图层进行分离,提高了程序的可维护性,降低了耦合性,这一框架模式也是从尚硅谷的教学中学习得来,‘真’ YYDS。在下面中分别对 尚硅谷 和 狗子我个人 的结构图进行展示,我的是基于尚硅谷的进行绘画的,主要是为了更好理解
-
尚硅谷
-
狗子本狗
三、工具类
在尚硅谷的文件中提供了已经封装好的 TSUtility 工具类,方便我们实现键盘的访问。由于工具类中涉及到的都已经接触过,因此这个工具类便自己进行了编写,如果是从视频那边过来的话也可以直接跳过工具类的编写,不过还是推荐自己尝试一下。
函数名 | 功能介绍 | 返回类型 |
---|---|---|
readMenuSelection | 用于界面菜单的选择 | int |
readInt | 从键盘中读取一个不超过二位数的整数 | int |
readConfirmSelection | 用于确认选择的输入,读取‘Y’或‘N’ | char |
readKeyBoard | 用于记录用户从键盘中输入的数据 | String |
readReturn | 提示并等待,直到用户按回车键后返回。 | void |
同样在这里附上一小撮截图
四、功能浅谈
1、 domain
这个模块是 MVC设计模式 里面的 M(model), 在这里封装了众多 JavaBean类,如员工职位和设备种类等
1.1、 员工类
-
Employee类
这是封装了普通员工信息的类,同时也是其余员工的直接或间接父类,其封装内容如下,分别为员工工号、员工姓名、员工年龄以及员工薪资,提供对应的构造器并在本类中重写了
toString()
方法来展示员工信息。
-
Programmer类
在本类中封装了程序员的信息,这也是加入团队的最低要求。这继承了 Employee 类,同时也是后面 Architect 类和 Designer 类的父类。除了继承了父类的属性之外,还封装了团队编号、状态情况以及设备情况,同时提供对应的构造器并在本类中重写了
toString()
方法来展示员工信息。
-
Designer类
在本类中封装了设计师的信息,这继承了 Programmer 类,同时也是后面 Architect 类的父类。除了继承了父类的属性之外,还封装了团队编号、状态情况以及设备情况,同时提供对应的构造器并在本类中重写了
toString()
方法来展示员工信息。
-
Architect类
在本类中封装了架构师的信息,这继承了 Designer 类。除了继承了父类的属性之外,还封装了股票数量属性,同时提供对应的构造器并在本类中重写了toString()
方法来展示员工信息。
1.2、 设备接口
由于在后续的操作中每个成员的设备并不明确,因此在这里定义一个设备接口,后方使用多态性从而减少代码的冗余。在其下面,PC类、NoteBook类 和 Printer类 都分别实现了这一接口并提供了对应的属性和方法(下方放的图是尚硅谷作图的,直接扒过来了)
2、 service
该模块是 MVC模式 中的 C(control),为实体对象(Employee及其子类如程序员等)的管理模块
2.1、 Data 类
这个是采用了尚硅谷的数据类,这里面记录了公司内所有的员工信息
public class Data {
public static final int EMPLOYEE = 10; //普通职工
public static final int PROGRAMMER = 11; //程序员
public static final int DESIGNER = 12; //设计师
public static final int ARCHITECT = 13; //架构师
public static final int PC = 21; //电脑
public static final int NOTEBOOK = 22; //笔记本
public static final int PRINTER = 23; //打印机
//Employee : 10, id, name, age, salary
//Programmer: 11, id, name, age, salary
//Designer : 12, id, name, age, salary, bonus
//Architect : 13, id, name, age, salary, bonus, stock
public static final String[][] EMPLOYEES = {
{"10", "1", "马 云", "22", "3000"},
{"13", "2", "马化腾", "32", "18000", "15000", "2000"},
{"11", "3", "李彦宏", "23", "7000"},
{"11", "4", "刘强东", "24", "7300"},
{"12", "5", "雷 军", "28", "10000", "5000"},
{"11", "6", "任志强", "22", "6800"},
{"12", "7", "柳传志", "29", "10800", "5200"},
{"13", "8", "杨元庆", "30", "19800", "15000", "2500"},
{"12", "9", "史玉柱", "26", "9800", "5500"},
{"11", "10", "丁 磊", "21", "6600"},
{"11", "11", "张朝阳", "25", "7100"},
{"12", "12", "杨致远", "27", "9600", "4800"}
};
//如下的EQUIPMENTS数组与上面的EMPLOYEES数组元素一一对应
//PC :21, model, display
//NoteBook:22, model, price
//Printer :23, name, type
public static final String[][] EQUIPMENTS = {
{},
{"22", "联想T4", "6000"},
{"21", "戴尔", "NEC17寸"},
{"21", "戴尔", "三星 17寸"},
{"23", "佳能 2900", "激光"},
{"21", "华硕", "三星 17寸"},
{"21", "华硕", "三星 17寸"},
{"23", "爱普生20K", "针式"},
{"22", "惠普m6", "5800"},
{"21", "戴尔", "NEC 17寸"},
{"21", "华硕", "三星 17寸"},
{"22", "惠普m6", "5800"}
};
}
2.2、 Status类
这是记录员工状态的类,将构造器私有化,只在类中声明三个对象属性,分别表示成员的空闲、繁忙和休假的状态。
public class Status {
private final String STATUS; //记录用户状态
private Status(String STATUS) {
this.STATUS = STATUS;
}
public static final Status FREE = new Status("FREE");
public static final Status BUSY = new Status("BUSY");
public static final Status VOCATION = new Status("VOCATION");
public String getSTATUS() {
return STATUS;
}
@Override
public String toString() {
return STATUS;
}
}
2.3、 TeamException 类
在本类中自定义了在团队操作过程中的操作异常
public class TeamException extends Exception {
static final long serialVersionUID = -7034897115645766939L;
public TeamException() {
}
public TeamException(String message) {
super(message);
}
}
2.4、 NameService 类
该类负责将 Data类 中的数据封装到 Employee[] 数组中,同时提供相关操作 Employee[] 的方法。
- 值得注意的是该类中的构造器的编写:
- 根据项目提供的Data类构建相应大小的 employees 数组
- 再根据 Data类 中的数据构建不同的对象,包括 Employee、Programmer、Designer 和 Architect 对象,以及相关联的 Equipment 子类的对象
- 将对象存于数组中
public NameListService() { employees = new Employee[EMPLOYEES.length]; //开辟公司员工个数大小的空间 //通过循环逐个创建不同工种的员工对象 for (int i = 0; i < EMPLOYEES.length; i++) { //获取每一个职位都有的属性 int type = Integer.parseInt(EMPLOYEES[i][0]); //工种 int id = Integer.parseInt(EMPLOYEES[i][1]); //工号 String name = EMPLOYEES[i][2]; //姓名 int age = Integer.parseInt(EMPLOYEES[i][3]); //年龄 double salary = Double.parseDouble(EMPLOYEES[i][4]); //工资 //特殊工种特定的属性获取 int stock; //声明股票数量 double bonus; //声明奖金 Equipment equipment; //声明设备变量 //通过不同的工种实例化不同的对象 switch(type) { case EMPLOYEE: { employees[i] = new Employee(id, name, age, salary); break; } case PROGRAMMER: { equipment = creatEquipment(i); //programmer 的设备 employees[i] = new Programmer(id, name, age, salary, equipment); break; } case DESIGNER: { bonus = Double.parseDouble(EMPLOYEES[i][5]); //designer 的奖金 equipment = creatEquipment(i); //designer 的设备 employees[i] = new Designer(id, name, age, salary, equipment, bonus); break; } case ARCHITECT: { bonus = Double.parseDouble(EMPLOYEES[i][5]); //architect 的奖金 equipment = creatEquipment(i); //architect 的设备 stock = Integer.parseInt(EMPLOYEES[i][6]); //architect 的股票数量 employees[i] = new Architect(id, name, age, salary, equipment, bonus, stock); break; } } } }
- 剩余方法介绍
方法名 | 功能 | 返回值 |
---|---|---|
getAllEmployees() | 获取所有员工信息 | Employee[] |
getEmployee | 通过 id 索引返回员工信息并有可能会抛出异常 | Employee |
creatEquipment | 根据不同的设备号创建不同的设备对象 | Equipment |
2.5、 TeamService 类
在这里封装了关于开发团队成员的管理方法,如添加、删除等,并封装了团队人数、架构师人数、设计师人数、程序员人数、团队最大容纳人数和用于自动生成团队成员编号的静态变量,同时提供了对应的 get() 方法
在这里对本类中的方法进行一个简单的介绍
- getTeam() : 用于获取开发团队的所有成员信息。无参数列表,返回值为 Programmer[];
- isExist() : 用于判断员工是否已经存在于团队。参数列表为需要判断的员工(Programmer p),返回值为 boolean;
- addMembe() : 用于添加团队成员,若该成员不存在,则抛出 TeamException 异常。参数列表为需要添加的员工(Employee e),无返回值;
- removeMember() : 用于通过在团队中的团队 Id 删除团队成员,若该成员不存在,则抛出 TeamException 异常。参数列表为需要移除的成员的团队成员编号(int memberId),返回值为空;
3、 view
这个模块是 MVC设计模式 里面的 V(view), 该模块为主控模块,负责菜单的显示和处理用户操作,几乎所有的交互都将在这一模块中完成。在本模块中包含了两个类,分别是 TSUtility 工具类以及 TeamView 类,其中工具类上方已经介绍过了,下面就主要介绍另外一个类。
3.1、 TeamView
在本类中通过与用户的交互,逐一实现各个功能。
类内部封装的属性有 listService 和 teamService 变量,都是供类中方法使用的,以及众多方法,通过 enterMainMenu() 方法在显示主菜单界面的同时,通过与用户的交互,从而进行调用其余方法。以下方法仅供 enterMainMenu() 方法调用:
listAllEmployees ()
:以表格形式列出公司所有成员getTeam()
:显示团队成员列表操作addMember ()
:实现添加成员操作deleteMember ()
:实现删除成员操作
public void enterMainMenu() {
boolean isLoop = true;
int selection = 0;
// TeamView menu = new TeamView(); //如果写成这样子的话就会出错,公司名单无法更新
while(isLoop) {
if(selection != 1) {
listAllEmployees(); //错误:menu.listAllEmployees();
}
System.out.print("1-团队列表 2-添加团队成员 3-删除团队成员 4-退出 请选择(1-4):");
selection = TSUtility.readMenuSelection();
switch(selection) {
case 1: {
listTeam(); //团队列表
break;
}
case 2: {
addMember(); //添加成员
break;
}
case 3: {
deleteMember(); //删除成员
break;
}
case 4: {
System.out.print("确认是否退出(Y/N):");
char confirm = TSUtility.readConfirmSelection();
if(confirm == 'Y') {
isLoop = false;
}
break;
}
}
}
}
这里需要注意的是在 enterMainMenu() 方法中注释的地方,狗子我找了半天之后终于找到了这个顽强的 bug((╬━㉨━)凸) ,初步怀疑是因为内存空间分配的原因,但不确定,因此去请教了我的老师。
- 老师给出的答案是在这里如果对该类进行实例化的话(TeamView menu = new TeamView()),就会在内存中生成另外一块空间,那么在调用下方的方法时,就会在这一块堆空间中进行操作,但是团队的对应操作是在本类中的空间进行操作的(因为在主函数中进行了实例化 new TeamView().enterMainMenu()),两块空间由于没有任何联系,因此对团队操作并不会影响到我们申请的 menu 空间,在测试时便会出错,具体 bug 情况可以自己去生产看看效果((ʘ̆㉨ʘ̆))
五、收获
怎么说呢,这次做的案例收获还是蛮多的,毕竟是结合了前面所学的 Java基础 进行一个整体复习的案例,不像前面两个一样只是部分的。
- 在这个案例中会发现到处都有多态的影子,这就让狗子我对多态性的理解更上一层楼,并且对其的运用也更加顺手
- 第二次使用 MVC设计框架 还是有点不一样的,对它的使用方式还是熟悉了很多,对多文件的情况可以很大程度上增加自己开发时的逻辑性。
- 最大的收获还是上面提及到的那个 bug ,这让我体会到了痛苦并快乐着的感觉(((유㉨유|||)))解决了这个 bug 之后会发现,自己对实例化这一块的掌握更多了,相对于之前只会用的程度上,感觉得到了升华
六、总结
对于Java基础来说,这个案例是三个案例里面相对全面的,可以较好的梳理和加强对Java三大特性的理解和使用,对之前的那句话 “你不动手,永远停留在想象层面” 感受更深了,毕竟也被一个 bug 折磨了一段时间。
这次的源码已经整理好了,一直决定这里的资源分享好像不太好使,因此抽空去学了一下 gitee码云 的基本用法并整理了这三次的源码放在 gitee 仓库中(别问为什么不放在 github 上,问了就是进入网址得看命)
gitee仓库地址 – > https://gitee.com/Aqting/javacase.git