一,写在前面:
✔✔在学完javase基础部分,许多知识带你还需我们巩固强化。下面我们一起来做一个小项目对先前知识进行一个梳理复习吧!该项目主要涉及:
(1)类的继承性和多态性
(2)对象的值传递、接口
(3)static和final修饰符
(4)特殊类的使用:包装类、抽象类、内部类
(5)异常处理
等知识点!🦇🦇🦇
二、需求说明
1.目标功能:
该软件实现以下功能:
🧭软件启动时,根据给定的数据创建公司部分成员列表(数组)
🔥根据菜单提示,基于现有的公司成员,组建一个开发团队以开发一个新的项目
🌞组建过程包括将成员插入到团队中,或从团队中删除某成员,还可以列出团队中现有成员的列表
🤑开发团队成员包括架构师、设计师和程序员
2.界面要求
对于初始化成员信息,需要根据Date类中的方法进行初始化顺序表
3.添加成员的类别限制
开发团队人员组成要求:
最多一名架构师
最多两名设计师
最多三名程序员
4.添加失败的原因
失败信息包含以下几种:
💖成员已满,无法添加
🌀该成员不是开发人员,无法添加
🚩该员工已在本开发团队中
👀该员工已是某团队成员
🏀该员正在休假,无法添加
🌟团队中至多只能有一名架构师
☀团队中至多只能有两名设计师
🌟团队中至多只能有三名程序员
三.框架搭建与结构分析
1Demain包
🌎关于设备相关类的设计
(1)关系图解:
从上面图中的表格不难看出,除了普通员工以外都有设备,而表格后面都显示设备信息,所以每一个设备类都应该有一个功能就是返回自身信息,所以我们将它设计成接口
(2)Equipment接口设计
package com.atbite.team.Domain;
public interface Equipment {
public abstract String getDescription();
}
(3)Printer类
package com.atbite.team.Domain;
public class Printer implements Equipment {
private String name;//型号
private String type; //显示器名称
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Printer(String name, String type) {
this.name = name;
this.type = type;
}
@Override
public String getDescription() {
return name+"("+type+")";
}
}
(4)Pc类
package com.atbite.team.Domain;
public class Pc implements Equipment{
private String model;//型号
private String display; //显示器名称
public Pc(){ };
public Pc(String model,String display){
this.model=model;
this.display=display;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getDisplay() {
return display;
}
public void setDisplay(String display) {
this.display = display;
}
public String getDescription(){
return model+"("+display+")";
}
}
(5)NoteBook类
package com.atbite.team.Domain;
public class Notebook implements Equipment{
private String model;//型号
double price; //显示器名称
public Notebook(String model,double price) {
this.model = model;
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String getDescription() {
return model+"("+price+")";
}
}
🌎关于员工相关类的设计
(1)关系图解
员工之间是一种继承关系:子类具有父类所有属性,同时又拥有独特是属性
(2)Employee(父类)
package com.atbite.team.Domain;
public class Employee {
private int id;
private String name;
private int age;
private double salary;
public Employee(){ }
public Employee(int id, String name, int age, double salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int 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 double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDetails(){
return id+"\t"+name+"\t\t"+age+"\t"+salary;
}
@Override
public String toString() {
return id+"\t"+name+"\t\t"+age+"\t"+salary;
}
}
(3)Programmer类
package com.atbite.team.Domain;
import com.atbite.team.service.Status;
public class Programmer extends Employee {
private int memberId;//团队编号
private Status status=Status.Free;
private Equipment equipment;
private Programmer(){
}
public Programmer(int id, String name, int age, double salary, Equipment equipment) {
super(id, name, age, salary);
this.equipment = equipment;
}
public int getMemberId() {
return memberId;
}
public void setMemberId(int memberId) {
this.memberId = memberId;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public Equipment getEquipment() {
return equipment;
}
public void setEquipment(Equipment equipment) {
this.equipment = equipment;
}
@Override
public String toString() {
return super.toString()+"\t程序员\t"+status+"\t\t\t"+equipment.getDescription();
}
public String getDetailsForm()
{
return memberId+"/"+"\t"+getName()+"\t"+getAge()+"\t"+getSalary()+"\t"+"程序员";
}
}
(4)Designer类
package com.atbite.team.Domain;
public class Designer extends Programmer {
private double bonus;
public Designer(int id, String name, int age, double salary, Equipment equipment, double bonus) {
super(id, name, age, salary, equipment);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public String toString() {
return getDetails() + "\t设计师\t" + getStatus() + "\t" + bonus + "\t\t" + getEquipment().getDescription();
}
public String getDetailsForm()
{
return getMemberId() + "/" + "\t" + getName() + "\t" + getAge() + "\t" + getSalary() + "\t" + "\t设计师\t"+bonus;
}
}
(5)Architect类
package com.atbite.team.Domain;
import java.util.Arrays;
public class Architect extends Designer{
private int stock;
public Architect(int id, String name, int age, double salary, Equipment equipment, double bonus, int stock) {
super(id, name, age, salary, equipment, bonus);
this.stock = stock;
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
@Override
public String toString() {
return getDetails()+"\t架构师\t"+getStatus()+"\t"+getBonus()+"\t"+stock+"\t"+getEquipment().getDescription();
}
public String getDetailsForm()
{
return getMemberId() + "/" + "\t" + getName() + "\t" + getAge() + "\t" + getSalary() + "\t" + "\t架构师\t"+getBonus()+"\t"+getStock();
}
}
2.Service包
(1)Date类存放公司员工数据数据
package com.atbite.team.service;
public class Date {
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
/**
* {"10", "1", "马云", "22", "3000"},
* {"13", "2", "马化腾", "32", "18000", "15000", "2000"},
*/
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)NameListService(初始化员工信息)
package com.atbite.team.service;
import com.atbite.team.Domain.*;
import static com.atbite.team.service.Date.*;
public class NameListService {
private Employee [] employees;
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]);
Equipment equipment;
double bonus;
int stock;
switch (type){
case EMPLOYEE:
employees[i]=new Employee(id,name,age,salary);
break;
case PROGRAMMER:
equipment=creatEquation(i);
employees[i]=new Programmer(id,name,age,salary,equipment);
break;
case DESIGNER:
equipment=creatEquation(i);
bonus=Double.parseDouble(EMPLOYEES[i][5]);
employees[i]=new Designer(id,name,age,salary,equipment,bonus);
break;
case ARCHITECT:
equipment=creatEquation(i);
bonus=Double.parseDouble(EMPLOYEES[i][5]);
stock=Integer.parseInt(EMPLOYEES[i][6]);
employees[i]=new Architect(id,name,age,salary,equipment,bonus,stock);
break;
}
}
}
private Equipment creatEquation(int index){
int type=Integer.parseInt(EQUIPMENTS[index][0]);
switch (type){
case PC:
return new Pc(EQUIPMENTS[index][1],EQUIPMENTS[index][2]);
case NOTEBOOK:
double price=Double.parseDouble(EQUIPMENTS[index][2]);
return new Notebook(EQUIPMENTS[index][1],price);
case PRINTER:
return new Printer(EQUIPMENTS[index][1],EQUIPMENTS[index][2]);
}
return null;
}
public Employee[] getAllEmployees(){
return employees;
}
public Employee getEmployee(int id)throws TeamException{
for (int i = 0; i <employees.length ; i++) {
if(employees[i].getId()==id){
return employees[i];
}
}
throw new TeamException("没有指定的员工");
}
}
(3)Status类(员工状态)
package com.atbite.team.service;
public class Status {
private final String NAME;
public String getNAME() {
return NAME;
}
private Status(String name) {
this.NAME = name;
}
public static final Status Free=new Status("FREE");
public static final Status BUSY=new Status("BUSY");
public static final Status VOCATION=new Status("VOCATION");
@Override
public String toString() {
return NAME;
}
}
(4)TeamService(团队列表)
package com.atbite.team.service;
import com.atbite.team.Domain.Architect;
import com.atbite.team.Domain.Designer;
import com.atbite.team.Domain.Employee;
import com.atbite.team.Domain.Programmer;
import java.util.Arrays;
public class TeamService {
/**
* counter为静态变量,用来为开发团队新增成员自动生成团队中的唯一ID,即memberId。(提示:应使用增1的方式)
* MAX_MEMBER:表示开发团队最大成员数
* team数组:用来保存当前团队中的各成员对象
* total:记录团队成员的实际人数
*/
private static int counter=1;
private final static int MAX_MEMBER=5;
Programmer [] team=new Programmer[MAX_MEMBER];//存放团队成员
private int total;//团队实际人数
public Programmer[] getTeam(){
Programmer[] team=new Programmer[this.total];
for (int i = 0; i < total; i++) {
team[i] = this.team[i];
}
return team;
}
public void addMember(Employee e)throws TeamException{
if(this.total==MAX_MEMBER)
{
throw new TeamException("团队已经满了");
}
if(!(e instanceof Programmer)){
throw new TeamException("该员工不是程序员");
}
if(check(e)){
throw new TeamException("该员工已经在团队中了");
}
Programmer pro=(Programmer)e;
if("BUSY".equalsIgnoreCase(pro.getStatus().getNAME()))
{
throw new TeamException("该员工已经在其他团队中");
}else if ("VOCATION".equalsIgnoreCase(pro.getStatus().getNAME())){
throw new TeamException("该员工正在度假");
}
/**
* 最多有一名架构师
* 最多有两名设计师
* 最多有3名程序员
* unreachable statement标记为运行时错误,一个unreachable statement就是编译器决定永远不会执行它。
* 下面的几种情况会出现 unreachable statement:
* (1)在reutrn语句后写语句。
* (2)在throw语句后写语句。
* (3)break、continue语句之后定义语句。
* (4)“\u10100”//合法,相当于‘\u1010’和字符串“0”。
* (5)移位运算符可以用于long int char short byte。
* (6)类的访问控制符可以是public或什么都不加。
* (7)goto是保留字但不是关键字。then什么都不是。
* (8)把超类的类型强制转换后赋给子类的对象时,编译无异常,但运行时会出现异常。
*/
int numOfDes = 0;
int numOfPrg = 0;
int numOfArch=0;
for (int i = 0; i < total; i++) {
if (team[i] instanceof Architect) numOfArch++;
else if (team[i] instanceof Designer) numOfDes++;
else numOfPrg++;
}
if (pro instanceof Architect) {
if (numOfArch >= 1) throw new TeamException("团队中至多只能有一名架构师");
} else if (pro instanceof Designer) {
if (numOfDes >= 2) throw new TeamException("团队中至多只能有两名设计师");
} else {
if (numOfPrg >= 3) throw new TeamException("团队中至多只能有三名程序员");
}
team[total++]=pro;
pro.setMemberId(counter++);
pro.setStatus(Status.BUSY);
}
private boolean check(Employee e){
for(int i=0;i<total;i++)
{
if(team[i].getId()==e.getId())
{
return true;
}
}
return false;
}
public void removeMember(int member)throws TeamException{
int i=0;
//包括member是负数的情况
//负数也会一直++到total
for(;i<total;i++){
if(team[i].getMemberId()==member){
team[i].setStatus(Status.Free);
break;
}
}
if(i==total)
{
throw new TeamException("没有这个员工");
}
for (int j = i+1; j <total ; j++) {
team[j-1]=team[j];
}
team[--total]=null;
}
}
(5)TeamException(自定义团队操作异常)
package com.atbite.team.service;
public class TeamException extends Exception {
static final long serialVersionUID = -3387516993124229948L;
public TeamException(){
super();
}
public TeamException(String s){
super(s);
}
}
3.View包(主界面设置)
(1)TSUtility(工具类)
package com.atbite.team.view;
import java.util.Scanner;
public class TSUtility {
private static Scanner scanner = new Scanner(System.in);
/**
*
* @Description 该方法读取键盘,如果用户键入’1’-’4’中的任意字符,则方法返回。返回值为用户键入字符。
* @author shkstart
* @date 2019年2月12日上午12:03:30
* @return
*/
public static char readMenuSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false);
c = str.charAt(0);
if (c != '1' && c != '2' &&
c != '3' && c != '4') {
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
/**
*
* @Description 该方法提示并等待,直到用户按回车键后返回。
* @author shkstart
* @date 2019年2月12日上午12:03:50
*/
public static void readReturn() {
System.out.print("按回车键继续...");
readKeyBoard(100, true);
}
/**
*
* @Description 该方法从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
* @author shkstart
* @date 2019年2月12日上午12:04:04
* @return
*/
public static int readInt() {
int n;
for (; ; ) {
String str = readKeyBoard(2, false);
try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
*
* @Description 从键盘读取‘Y’或’N’,并将其作为方法的返回值。
* @author shkstart
* @date 2019年2月12日上午12:04:45
* @return
*/
public static char readConfirmSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false).toUpperCase();
c = str.charAt(0);
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}
private static String readKeyBoard(int limit, boolean blankReturn) {
String line = "";
while (scanner.hasNextLine()) {
line = scanner.nextLine();
if (line.length() == 0) {
if (blankReturn) return line;
else continue;
}
if (line.length() < 1 || line.length() > limit) {
System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
continue;
}
break;
}
return line;
}
}
(2)TeamView(主函数设计)
package com.atbite.team.view;
import com.atbite.team.Domain.Employee;
import com.atbite.team.Domain.Programmer;
import com.atbite.team.service.NameListService;
import com.atbite.team.service.TeamException;
import com.atbite.team.service.TeamService;
import java.util.List;
public class TeamView {
private NameListService listSvc= new NameListService();
private TeamService nameSvc= new TeamService();
public void enterMainMenu(){
boolean loopBool=true;
char c='0';
while (loopBool){
//细节
if(c!='1'){
listAllEmployees();
}
System.out.println("1-团队列表 2-添加团队成员 3-删除团队成员 4-退出 请选择(1-4):");
c=TSUtility.readMenuSelection();
switch (c){
case '1':
getTeam();
break;
case '2':
addMember();
break;
case '3':
deleteMember();
break;
case '4':
System.out.println("你确认退出吗!(Y/N)");
char a=TSUtility.readConfirmSelection();
if(a=='Y')
{
loopBool=false;
}
break;
}
}
}
private void listAllEmployees(){
System.out.println("\n-------------------------------开发团队调度软件--------------------------------\n");
Employee [] employees= listSvc.getAllEmployees();
if (employees.length == 0) {
System.out.println("没有客户记录!");
} else {
System.out.println("ID\t姓名\t\t年龄\t\t工资\t\t职位\t\t状态\t奖金\t股票\t领用设备");
}
for (Employee e:employees
) {
System.out.println(" "+e);
}
System.out.println("-------------------------------------------------------------------------------");
}
/**
* getTeam():void
* - addMember(): void
* - deleteMember(): void
* + main(args: String[]) : void
*/
private void getTeam(){
System.out.println("\n--------------------团队成员列表---------------------\n");
Programmer[]programmers=nameSvc.getTeam();
if(programmers==null||programmers.length==0)
{
System.out.println("开发团队还没有成员");
}else {
System.out.println("TID/ID\t姓名\t年龄\t工资\t职位\t奖金\t股票");
}
for (Programmer p:programmers
) {
System.out.println(" "+p.getDetailsForm());
}
System.out.println("-------------------------------------------------------------------------------");
}
private void addMember(){
System.out.println("---------------------添加成员---------------------");
System.out.print("请输入要添加的员工ID:");
int id = TSUtility.readInt();
Employee employee= null;
try {
employee = listSvc.getEmployee(id);
nameSvc.addMember(employee);
System.out.println("添加成功");
//按回车继续
TSUtility.readReturn();
} catch (TeamException e) {
System.out.println("添加失败,原因:"+e.getMessage());
}
}
private void deleteMember() {
System.out.println("---------------------删除成员---------------------");
System.out.println("请输入要删除员工的id");
int id=TSUtility.readInt();
System.out.println("确认要删除吗?(Y/N)");
char c=TSUtility.readConfirmSelection();
if(c=='N')
{
return;
}
try {
nameSvc.removeMember(id);
System.out.println("删除成功!");
} catch (TeamException e) {
System.out.println("删除失败,原因:"+e.getMessage());
}
TSUtility.readReturn();
}
public static void main(String[] args) {
TeamView view=new TeamView();
view.enterMainMenu();
}
}
四.效果展示: