上篇的基于文本界面的客户管理系统是使用的面向对象的基本特性完成的,今天这个项目是运用面向对象的高级特性完成的。
一、先看一下项目结构:
效果图:
主要涉及到以下知识点:
- 类的继承和多态
- 对象的关联
- static和final修饰符
- 特殊类的使用
- 异常处理
该系统实现一下的功能:
- 系统启动时根据给定的数据,创建公司部分成员列表(数组)
- 根据菜单提示,基于现有的公司成员,调度人员组建一个新的开发团队,用以开发一个新的项目
- 组建个过程包括将成员插入到团队,或从团队中删除某个成员,还可以显示列出团队现有的成员列表
- 团队开发包括架构师,设计师和程序员
多层继承:
①提高代码复用性
②子类是父类的特殊类型(多态)
二、包说明:
1、com.team.domain:模块中包含了所有实体类:(其中程序员(Programmer)及其子类,均会领用某种电子设备(Equipment))
2、com.team.service:实体对象(Employee及其子类如程序员等)的管理模块, NameListService和TeamService类分别用各自的数组来管理公司员工和开发团队成员对象(重点注意)
3、com.team.service.test:用来测试
4、com.team.util:存放工具类
5、com.team.view:模块为主控模块,负责菜单的显示和处理用户操作
三、注意事项
1、添加功能的要求
- 成员已满,无法添加
- 该成员不是开发人员,无法添加
- 该员已是团队成员
- 该员正在休假,无法添加
- 团队中只能有一名架构师
- 团队中只能有两名设计师
- 团队中只能有三名程序员
2、删 / 添加 都会发生改变的量
- 团队成员的状态
- 团队成员的numberId
- 团队的总人数
3、数组删除的情况
先查找是否在数组中,从要删除的下标开始到最后一位下标减一 ,从后面依次向前覆盖 ,最后的下标位置置空,且总人数减少一
4、项目中提供了TSUtility.java类,可用来方便地实现键盘访问。
该类提供了以下静态方法:
public static char readMenuSelection()
用途:该方法读取键盘,如果用户键入’1’-’4’中的任意字符,则方法返回。返回值为用户键入字符。
public static void readReturn()
用途:该方法提示并等待,直到用户按回车键后返回。
public static int readInt()
用途:该方法从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
public static char readConfirmSelection() :
用途:从键盘读取‘Y’或’N’,并将其作为方法的返回值。
5、 继承Employee的Programmer、Designer、Architect分别重写了toString()方法与getMemberInfo(),用于显示公司员工信息与团队员工信息
6、实现Equipment接口的PC、Printer、NoteBook分别重写了getDiscription()方法,用于对分类的设备进行描述(接口中定义了一个getDiscription()方法)
注:
这里主要贴出管理公司成员的类NameListService.java
和管理团队成员的类TeamService.java以及负责菜单的显示和处理用户操作TeamView.java
实体类、测试类、工具类、接口枚举类、及自定义异常类就不贴了
NameListService.java
package com.team.service; import com.team.domain.Architcet; import com.team.domain.Designer; import com.team.domain.Employee; import com.team.domain.Equipment; import com.team.domain.NoteBook; import com.team.domain.PC; import com.team.domain.Printer; import com.team.domain.Programmer; /** * 管理员工对象 * * @author Administrator * */ public class NameListService { // 创建员工数组 private Employee[] employees = null; /* * 将数组中的信息进行抽取 根据类型封装成对象 1、获取员工的类型 2、获设备的类型 */ public NameListService() { // 首先初始化数组 employees = new Employee[Data.EMPLOYEES.length]; for (int i = 0; i < employees.length; i++) { // 根据数组长度遍历获取员工数组的内容 int type = Integer.parseInt(Data.EMPLOYEES[i][0]); int id = Integer.parseInt(Data.EMPLOYEES[i][1]); String name = Data.EMPLOYEES[i][2]; int age = Integer.parseInt(Data.EMPLOYEES[i][3]); // 根据二维数组的成员类型初始化对应的对象,并添加到员工数组中 Double salary = Double.parseDouble(Data.EMPLOYEES[i][4]); // 将公共的部分提取到外部来,防止每次创建 double bonus = 0; // 根据员工的类型创建相应的对象 switch (type) { case Data.EMPLOYEE: Employee employee = new Employee(id, name, salary, age); employees[i] = employee; break; case Data.PROGRAMMER: Programmer programmer = new Programmer(id, name, salary, age, createEquipment(i)); employees[i] = programmer; break; case Data.DESIGNER: bonus = Double.parseDouble(Data.EMPLOYEES[i][5]); Designer designer = new Designer(id, name, salary, age, createEquipment(i), bonus); employees[i] = designer; break; case Data.ARCHITECT: bonus = Double.parseDouble(Data.EMPLOYEES[i][5]); int stock = Integer.parseInt(Data.EMPLOYEES[i][6]); Architcet architcet = new Architcet(id, name, salary, age, createEquipment(i), bonus, stock); employees[i] = architcet; break; } } } /* * 创建设备 */ public Equipment createEquipment(int i) { // TODO Auto-generated method stub // 获取设备的类型和名字 String type = Data.EQIPMENTS[i][0]; String model = Data.EQIPMENTS[i][1]; // 根据获取的类型 再次获取对应的对象 switch (Integer.parseInt(type)) { case Data.PC: String display = Data.EQIPMENTS[i][2]; PC pc = new PC(model, display); return pc; case Data.NOTEBOOK: double price = Double.parseDouble(Data.EQIPMENTS[i][2]); NoteBook noteBook = new NoteBook(model, price); return noteBook; case Data.PRINTER: String equipmentType = Data.EQIPMENTS[i][2]; Printer printer = new Printer(model, equipmentType); return printer; } return null; } /* * 获取所有员工 */ public Employee[] getAllEmployee() { return employees; } /* * 根据输入的id获取对应的员工 */ public Employee getEmployee(int id) throws TeamExpection{ for (int j = 0; j < employees.length; j++) { /*if (id == Integer.parseInt(Data.EMPLOYEES[j][1])) { return employees[j]; }*/ if (id == employees[j].getId()) { return employees[j]; } } throw new TeamExpection("不存在该员工"); //return null; } public static void main(String[] args) { } }TeamService.java
package com.team.service; import com.team.domain.Architcet; import com.team.domain.Designer; import com.team.domain.Employee; import com.team.domain.Programmer; import com.team.domain.Status; import javafx.scene.web.PromptData; public class TeamService { // 团队成员id private int counter = 1; // 当前团队成员的最大数量 private final int MAX_MEMBER = 5; // 用来存放当前团队的成员 private Programmer[] team = new Programmer[MAX_MEMBER]; // 统计当前团队的人是 private int total = 0; /* * 获取团队中的成员 */ public Programmer[] getTeam() { // 重新键一个数组,将原来的成员写进去 Programmer[] p = new Programmer[total]; for (int i = 0; i < total; i++) { p[i] = team[i]; } return p; } /* * 添加团队成员 */ // 成员已满,无法添加 // 该成员不是开发人员,无法添加 // 该员已是团队成员 // 该员正在休假,无法添加 // 团队中只能有一名架构师 // 团队中只能有两名设计师 // 团队中只能有三名程序员 public void addMember(Employee e) throws TeamExpection { //成员已满,无法添加 if (total >= team.length) { throw new TeamExpection("成员已满,无法添加"); } //该成员不是开发人员,无法添加 if (!(e instanceof Programmer)) { throw new TeamExpection("该成员不是开发人员,无法添加"); } //该成员已是团队成员 for (int i = 0; i < total; i++) { if (e.getId() == team[i].getId()) { throw new TeamExpection("该员已是团队成员"); } } //该成员正在休假,无法添加 //将传进来的对象进行判断,注意千万不可将已存在的成员判断 Programmer p1 = (Programmer) e; if (p1.getStatus() == Status.VOCATION) { throw new TeamExpection("该员正在休假,无法添加"); } // 团队中只能有一名架构师 // 团队中只能有两名设计师 // 团队中只能有三名程序员 // 先统计每个职位各有多少人员,在进行判断抛异常 int proCount = 0; int desCount = 0; int arcCount = 0; for (int i = 0; i < team.length; i++) { Programmer p2 = team[i]; if (p2 instanceof Architcet) { arcCount++; } else if (p2 instanceof Designer) { desCount++; } else if (p2 instanceof Programmer) { proCount++; } } //p2 是团队中的程序员 p1是传进来要添加为团队成员的程序员 if (p1 instanceof Architcet) { if (arcCount >= 1) { throw new TeamExpection("团队只能有一名架构师"); } } else if (p1 instanceof Designer) { if (desCount >= 2) { throw new TeamExpection("团队中只能有两名设计师"); } } else if (p1 instanceof Programmer) { if (proCount >= 3) { throw new TeamExpection("团队中只能有三名程序员"); } } // 添加成员到到团队中 team[total++] = p1; // 改变成员的状态 p1.setStatus(Status.BUSY); // 设置团队 成员id p1.setMemberId(counter++); } /* * 删除团队成员 */ public void deleteMember(int memberId) throws TeamExpection { //查找memberId是否在该团队中 int j = 0; for (; j < total; j++) { if (team[j].getMemberId() == memberId) { team[j].setStatus(Status.FREE); break; } } //如果查不到在该团队中,就抛出异常 if (j >= total) { throw new TeamExpection("没有找到对应的成员"); } for (int i = j; i < total-1; i++) { team[i] = team[i + 1]; } team[total - 1] = null; total--; } }TeamView.java
package com.team.view; import com.team.domain.Employee; import com.team.domain.Programmer; import com.team.service.NameListService; import com.team.service.TeamExpection; import com.team.service.TeamService; import com.team.util.TSUtility; public class TeamView { NameListService nameListService = new NameListService(); TeamService teamService = new TeamService(); /* * 进入主菜单 * 主要点:1、遍历输出实体类重写的每个toString()方法 * 2、读取菜单选项 */ public void listMainMenu() { boolean isFlag = true; do { System.out.println("-------------------------------开发团队调度软件--------------------------------"); System.out.println("ID\t姓名\t年龄\t工资\t职位\t状态\t奖金\t股票\t领用设备"); Employee[] allEmployee = nameListService.getAllEmployee(); for (int i = 0; i < allEmployee.length; i++) { // 调用每个实体类 对应的toString()方法 System.out.println(allEmployee[i].toString()); } System.out.println("---------------------------------------------------------------------------"); System.out.print("1-团队列表 2-添加团队成员 3-删除团队成员 4-退出 请选择(1-4):"); // 读取菜单选项 char readMenuSelection = TSUtility.readMenuSelection(); switch (readMenuSelection) { case '1': this.listTeamAllEmployee(); break; case '2': addEmployee(); break; case '3': deleteEmployee(); break; case '4': System.out.println("是否退出(Y/N)?:"); char readConfirmSelection = TSUtility.readConfirmSelection(); if (readConfirmSelection == 'Y') { isFlag = false; } System.out.println("你以退出系统!!!"); break; } } while (isFlag); } /* * 删除团队成员 */ public void deleteEmployee() { // TODO Auto-generated method stub System.out.print("请输入要删除员工的TID:"); int readInt = TSUtility.readInt(); System.out.print("确认是否删除(Y/N)"); char confirmSelection = TSUtility.readConfirmSelection(); if (confirmSelection =='Y') { try { teamService.deleteMember(readInt); System.out.println("刪除成功"); } catch (TeamExpection e) { // TODO Auto-generated catch block System.out.println(e.getMessage()); } } } /* * 添加团队成员 * 主要点:调用业务逻辑类的方法getEmployee(),判断成员是否存在 */ public void addEmployee() { // TODO Auto-generated method stub System.out.print("请输入要添加的员工ID:"); int readInt = TSUtility.readInt(); //判断员工是否存在 Employee employee = null; try { employee = nameListService.getEmployee(readInt); teamService.addMember(employee); System.out.println("添加成功"); } catch (TeamExpection e) { // TODO Auto-generated catch block System.out.println(e.getMessage()); } //按回车继续 TSUtility.readReturn(); } /* * 显示团队列表 * 主要点: * 1、判空 * 2、遍历输出实体类重写的每个getMemberInfo()方法 */ public void listTeamAllEmployee() { // TODO Auto-generated method stub System.out.println("--------------------团队成员列表---------------------"); System.out.println("TID/ID 姓名 年龄 工资 职位 奖金 股票"); Programmer[] team = teamService.getTeam(); if (team.length>0 && team!=null) { for (int i = 0; i < team.length; i++) { // 调用每个实体类 对应的getMemberInfo()方法 System.out.println(team[i].getMemberInfo()); } }else { System.out.println("目前团队没人,赶紧组织团队!!M"); } //System.out.println("添加成功。。。"); TSUtility.readReturn(); } public static void main(String[] args) { new TeamView().listMainMenu(); } }
项目地址:https://download.csdn.net/download/mxcsdn/10366576
上篇面向对象的基本特性: 基于文本界面的客户信息管理系统-纯面向对象
.