一、准备工作
1.先创建好三个包用来分别存放不同的类
2.
package view;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* 目中提供了TSUtility.java类,可用来方便地实现键盘访问。
*
* @author : Crazy_August
* @Date: 2021-02-28
* @Time: 17:06
*/
public class TSUtility {
private static Scanner scanner = new Scanner(System.in);
/**
* @return
* @Description 该方法读取键盘,如果用户键入’1’-’4’中的任意字符,则方法返回。返回值为用户键入字符。
* @author shkstart
* @date 2019年2月12日上午12:03:30
*/
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);
}
/**
* @return
* @Description 该方法从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
* @author shkstart
* @date 2019年2月12日上午12:04:04
*/
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;
}
/**
* @return
* @Description 从键盘读取‘Y’或’N’,并将其作为方法的返回值。
* @author shkstart
* @date 2019年2月12日上午12:04:45
*/
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;
}
}
在包中导入已经提供的Data类(导入到serve包中)和TSUtility(导入到view包中)工具类
package serve;
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
/**
* {"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"}
};
}
二、创建Equipment接口及其实现类:
1、在domain包中创建Equipment接口
package domain;
public interface Equipment {
public String getDescription();
}
2、创建Equipment的实现类PC以及重写getDescription()方法
package domain;
public class PC implements Equipment{
private String model;
private String display;
public PC(String model,String display) {
this.model = model;
}
public PC() {
}
public String getDisplay() {
return display;
}
public void setDisplay(String display) {
this.display = display;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String getDescription() {
return model+"("+display+")";
}
}
3、创建NoteBook实现类
package domain;
public class Notebook implements Equipment {
private String model;
private double price;
public Notebook(String model,double price) {
this.model = model;
this.price=price;
}
public Notebook(){
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getDescription() {
return model+"("+price+")";
}
}
4、创建Printer实现类
package domain;
public class Printer implements Equipment{
private String model;
private String type;
public String getType() {
return type;
}
public Printer(String model, String type) {
this.model = model;
this.type = type;
}
public void setType(String type, String model) {
this.type = type;
this.model=model;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String getDescription() {
return model+"("+type+")";
}
}
四、创建Employee类及其它的子类
1.创建Employee类
设置id,name,age,salary四个属性以及get和set方法和构造器。
再重写toString方法以便后面输出Employee(重写Employee的toString方法的时候有个小细节,因为id,name,和age,salary是共有的几个属性 所以Employee类中可以写一个getString方法方便其子类重写toString方法)
package domain;
public class Employee {
int id;
String name;
int age;
double 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 Employee(int id, String name, int age, double salary) {
super();
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
public Employee(){}
public String getString(){
return id + "\t" + name + "\t"+ age + "\t"+ salary ;
}
public String toString(){
return getString();
}
}
2、在serve包中创建Status(员工状态)类
Status类似于之前学的单例模式,它唯一的不同就是它是“三例模式"
写法:1.私有化构造器 2.创建自身类的对象 3.写get方法 4.重写toString方法。
package serve;
public class Status {
private String Name;
private Status(String name){
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");
public String getName(){
return Name;
}
public String toString(){
return Name;
}
}
3、创建Employee的子类Programmer类
比Employee类中多了Status属性和Equipment属性;以及再写一个toteam方法以便用户查看团队成员信息时可以输出成员的memberid和其他属性:
package domain;
import serve.Status;
public class Programmer extends Employee{
public Programmer(){}
private int memberid;
private Status status;
private Equipment equipment;
public Programmer(int id, String name, int age, double salary, Status status, Equipment equipment) {
super(id, name, age, salary);
this.status = status;
this.equipment = equipment;
}
public Equipment getEquipment() {
return equipment;
}
public void setEquipment(Equipment equipment) {
this.equipment = equipment;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public int getMemberid() {
return memberid;
}
public void setMemberid(int memberid) {
this.memberid = memberid;
}
public String toString(){
return getString() +"\t程序员\t"+status+"\t\t\t\t\t"+equipment.getDescription();
}
public String toteam(){
return getMemberid() + "\t" + getId() + "\t" + getName() + "\t" + getAge() + "\t\t" + getSalary() + "\t\t程序员";
}
}
4.创建Programmer类的子类Designer类
比Programmer类中多了个bouns(奖金)属性
package domain;
import serve.Status;
public class Designer extends Programmer{
private double bouns;
public double getBouns() {
return bouns;
}
public void setBouns(double bouns) {
this.bouns = bouns;
}
public Designer(int id, String name, int age, double salary, Status status, Equipment equipment,
double bouns) {
super(id, name, age, salary, status, equipment);
this.bouns = bouns;
}
@Override
public String toString() {
return getString()+"\t设计师\t"+getStatus()+"\t"+bouns+"\t\t\t"+getEquipment().getDescription();
}
public String toteam(){
return getMemberid() + "\t" + getId() + "\t" + getName() + "\t" + getAge() + "\t\t" + getSalary() + "\t\t设计师\t" + getBouns() ;
}
}
5、创建Designer类的子类Architect类
Architect类比的父类也只多了个stock(股票)属性,写起来也没有什么难度;
package domain;
import serve.Status;
public class Architect extends Designer{
private int stock;
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
public Architect(int id, String name, int age, double salary, Status status, Equipment equipment,
double bouns, int stock) {
super(id, name, age, salary, status, equipment, bouns);
this.stock = stock;
}
@Override
public String toString() {
return getString()+"\t架构师\t"+getStatus()+"\t"+getBouns()+"\t"+stock+"\t"+getEquipment().getDescription();
}
public String toteam(){
return getMemberid() + "\t" + getId() + "\t" + getName() + "\t" + getAge() + "\t\t" + getSalary() + "\t\t架构师\t" + getBouns() + "\t" + stock;
}
}
四、在serve包中创建NameList类
1、在构造器中需要把Data中的Employees信息全部创建成对象并且存储到Employee型数组中
其中有个获取Equipment型的属性是一个难点所以在构造器中写一个getEquipment方法用来得到员工的equipment属性
private Equipment getEquipment(int i){
int key=Integer.parseInt(Data.EQUIPMENTS[i][0]);
String model=Data.EQUIPMENTS[i][1];
switch (key){
case Data.PC:
String display=Data.EQUIPMENTS[i][2];
return new PC(model,display);
case Data.NOTEBOOK:
double price = Double.parseDouble(Data.EQUIPMENTS[i][2]);
return new NoteBook(model,price);
case Data.PRINTER:
String type = Data.EQUIPMENTS[i][2];
return new Printer(Data.EQUIPMENTS[i][1], type);
}
return null;
}
所以构造器中的写法为
public NameList(){
for (int i=0;i<Data.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]);
Equipment equipment;
Status status=Status.FREE;
int memberid=0;
switch (type){
case Data.EMPLOYEE:
employee[i]=new Employee(id,name,age,salary);
break;
case Data.PROGRAMMER:
equipment=getEquipment(i);
employee[i]=new Pragrammer(id,name,age,salary,status,memberid,equipment);
break;
case Data.DESIGNER:
equipment=getEquipment(i);
double bouns=Double.parseDouble(Data.EMPLOYEES[i][5]);
employee[i]=new Designer(id,name,age,salary,status,memberid,equipment,bouns);
break;
case Data.ARCHITECT:
equipment=getEquipment(i);
double b=Double.parseDouble(Data.EMPLOYEES[i][5]);
int stock=Integer.parseInt(Data.EMPLOYEES[i][6]);
employee[i]=new Architect(id,name,age,salary,status,memberid,equipment,b,stock);
break;
default:
throw new IllegalStateException("Unexpected value: " + type);
}
}
}
2.getAllEmployee方法
public Employee[] getAllEmployee(){
return employee;
}
3.创建一个自定义的异常类TeamException
package serve;
public class TeamException extends Exception{
static final long serialVersionUID = -1702031019931249948L;
public TeamException(String mesage){
super(mesage);
}
}
4.书写NameList中的getEmployee方法
public Employee getEmployee(int index)throws TeamException{
if(index<0||index>this.employees.length){
throw new TeamException("找不到指定的员工!");
}
return employees[index-1];
}
}
NameList完整代码如下
package serve;
import domain.*;
public class NameList {
private Employee []employee=new Employee[Data.EMPLOYEES.length];
public NameList(){
for (int i=0;i<Data.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]);
Equipment equipment;
Status status=Status.FREE;
int memberid=0;
switch (type){
case Data.EMPLOYEE:
employee[i]=new Employee(id,name,age,salary);
break;
case Data.PROGRAMMER:
equipment=getEquipment(i);
employee[i]=new Pragrammer(id,name,age,salary,status,memberid,equipment);
break;
case Data.DESIGNER:
equipment=getEquipment(i);
double bouns=Double.parseDouble(Data.EMPLOYEES[i][5]);
employee[i]=new Designer(id,name,age,salary,status,memberid,equipment,bouns);
break;
case Data.ARCHITECT:
equipment=getEquipment(i);
double b=Double.parseDouble(Data.EMPLOYEES[i][5]);
int stock=Integer.parseInt(Data.EMPLOYEES[i][6]);
employee[i]=new Architect(id,name,age,salary,status,memberid,equipment,b,stock);
break;
default:
throw new IllegalStateException("Unexpected value: " + type);
}
}
}
private Equipment getEquipment(int i){
int key=Integer.parseInt(Data.EQUIPMENTS[i][0]);
String model=Data.EQUIPMENTS[i][1];
switch (key){
case Data.PC:
String display=Data.EQUIPMENTS[i][2];
return new PC(model,display);
case Data.NOTEBOOK:
double price = Double.parseDouble(Data.EQUIPMENTS[i][2]);
return new NoteBook(model,price);
case Data.PRINTER:
String type = Data.EQUIPMENTS[i][2];
return new Printer(Data.EQUIPMENTS[i][1], type);
}
return null;
}
public Employee[] getAllEmployee(){
return employee;
}
public Employee getEmployee(int i)throws TeamException{
if(i>Data.EMPLOYEES.length||i<=0){
throw new TeamException("找不到指定员工");
}
return employee[i-1];
}
}
五、在serve包中创建TeamServe类
1、添加团队成员方法(addMember)
添加团队成员时要满足以上要求才能添加成功;
2、removeMember(删除成员)方法
①定义一个int型i,遍历team[]数组中的成员有没有与之匹配的memberid 找到即修改;
②要是i==total说明找不到与之匹配的成员,则抛出一个异常
③如果代码能通过②则继续修改team数组
3、返回所有团队成员
new一个Programmer数组和现有的team数组等长 然后返回
TeamServe完整代码
package serve;
import domain.Architect;
import domain.Designer;
import domain.Employee;
import domain.Pragrammer;
public class TeamServe {
private int MaxTeam=5;
private int total=0;
private int count=1;
private Pragrammer[]team=new Pragrammer[MaxTeam];
public void addMember(Employee e)throws TeamException {
//该员工不是开发人员
if(!(e instanceof Pragrammer)){
throw new TeamException("该员工不是开发人员");
}
//团队成员已满·
if(total>=MaxTeam){
throw new TeamException("团队成员已满");
}
//该员工在本团队中
int numP=0,numD=0,numA=0;
for(int i=0;i<total;i++){
if(team[i].getId()==e.getId()){
throw new TeamException("该成员已在本团队中");
}
}
Pragrammer p=(Pragrammer) e;
//该成员在休假
if(p.getStatus()==Status.VOCATION){
throw new TeamException("该员工正在休假");
}
//该员工的状态为BUSY
if(p.getStatus()==Status.BUSY){
throw new TeamException("该员工已在别的开发团队");
}
//遍历统计程序员,设计师,架构师的数量
for (int i=0;i<team.length;i++){
if(team[i]instanceof Architect){
numA++;
}else if(team[i] instanceof Designer){
numD++;
}else if(team[i] instanceof Pragrammer){
numP++;
}
}
//判断架构师是否满员了;
if(p instanceof Architect){
if (numA>=1){
throw new TeamException("架构师已满");
}
}
//判断设计师是否满员;
if(p instanceof Designer){
if(numD>=2){
throw new TeamException("设计师已满");
}
}
//判断程序员是否满员;
if(p instanceof Pragrammer){
if(numP>=3){
throw new TeamException("程序员已满");
}
}
team[total]=p;
total++;
p.setMemberid(count);
count++;
p.setStatus(Status.BUSY);
}
//根据memberid来删除团队成员;
public void removeMember(int index)throws TeamException{
int i=0;
for ( ;i<total;i++){
if(team[i].getMemberid()==index){
team[i].setStatus(Status.FREE);
break;
}
}
//如果i能等于total了说明循环遍历了一遍没有找到该成员,所以这时候可以抛出异常结束此方法;
if(i==total){
throw new TeamException("该团队没有这个成员");
}
//如果方法能走到这一步,则说明已经找到该成员了,那么就进行修改;
for (int j=index-1;j<total-1;j++){
team[j]=team[j+1];
}
team[total]=null;
total--;
}
//返回团队方法
public Pragrammer[] getTeam(){
//new一个等长的数组进行返回
Pragrammer[]pragrammers=new Pragrammer[total];
for (int i=0;i<pragrammers.length;i++){
pragrammers[i]=team[i];
}
return pragrammers;
}
}
六、创建EmployeeView(和用户交互)类
1、创建一个输出所有员工信息的方法
2、创建输出所有团队成员的方法
3、创建增加团队成员方法
4、创建删除成员的方法
5、写一个菜单方法搭起框架并写好退出逻辑
完整代码如下
package view;
import domain.Employee;
import domain.Pragrammer;
import serve.NameList;
import serve.TeamException;
import serve.TeamServe;
import java.lang.reflect.Parameter;
public class EmployeeView {
NameList nameList=new NameList();
TeamServe teamServe=new TeamServe();
//先写一个输出所以员工信息的方法
public void listAllEmployee(){
System.out.println("------------------------------------开发团队调度软件---------------------------------------");
System.out.println("ID\t姓名\t\t年龄\t工资\\t\t职位\t\t状态\t\t奖金\t\t股票\t\t领用设备");
Employee []employee=nameList.getAllEmployee();
for (int i=0;i<employee.length;i++){
System.out.println(employee[i]);
}
System.out.println("-----------------------------------------------------------------------------------------");
}
//输出团队信息的方法
public void teamAll(){
Pragrammer[]team=teamServe.getTeam();
if(team==null||team.length==0){
System.out.println("开发团队中没有任何员工");
}else {
System.out.println("tid/id\t姓名\t\t年龄\t\t工资\t\t\t职位\t\t奖金\t\t股票");
for (int i=0;i<team.length;i++){
System.out.println(team[i].toteam());
}
}
System.out.println("****************************************************************");
}
//添加团队成员方法
public void addTeam(){
System.out.println("--------------------------添加成员----------------------------------");
System.out.println("请输入要添加的员工id:");
int index=TSUtility.readInt();
try {
Employee employee=nameList.getEmployee(index);
teamServe.addMember(employee);
System.out.println("成员添加成功");
} catch (TeamException e) {
System.out.println("添加失败"+e.getMessage());
}
TSUtility.readReturn();
}
//删除成员方法;
public void removeMember(){
System.out.println("--------------------------删除成员----------------------------------");
System.out.println("请输入要删除的员工mid:");
int memberId = TSUtility.readInt();
System.out.print("确认是否删除(Y/N):");
char is=TSUtility.readConfirmSelection();
if(is=='Y'){
try {
teamServe.removeMember(memberId);
System.out.println("删除成功");
} catch (TeamException e) {
System.out.println("删除失败"+e.getMessage());
}
}
TSUtility.readReturn();
}
//主菜单
public void menu(){
boolean isflag=true;
char type=0;
while (isflag){
if(type!='1'){
listAllEmployee();
}
System.out.println("1- 团队成员 2- 添加团队成员 3-删除团队成员 4-退出 请选择( 1 - 4 ) ");
type=TSUtility.readMenuSelection();
switch (type){
case '1':
teamAll();
break;
case '2':
addTeam();
break;
case '3':
removeMember();
case '4':
System.out.println("确认是否退出( Y/N ):");
char isexit=TSUtility.readConfirmSelection();
if(isexit=='Y'){
isflag=false;
}
break;
}
}
}
public static void main(String[] args) {
EmployeeView employeeView=new EmployeeView();
employeeView.listAllEmployee();
employeeView.menu();
}
}
七、代码完成后效果