项目二_客户信息管理软件

目 标

  • 模拟实现一个基于文本界面的《客户信息管理软件》
  • 进一步掌握编程技巧和调试技巧,熟悉面向对象编程
  • 主要涉及以下知识点:
    • 类结构的使用:属性、方法及构造器
    • 对象的创建与使用
    • 类的封装性
    • 声明和使用数组
    • 数组的插入、删除和替换
    • 关键字的使用:this

需求说明

模拟实现基于文本界面的《客户信息管理软件》。
该软件能够实现对客户对象的插入、修改和删除(用数组实现),并能够打印客户明细表。
项目采用分级菜单方式。主菜单如下:

1
2
3
4
5
6
7
8
9
-----------------客户信息管理软件-----------------

1 添 加 客 户
2 修 改 客 户
3 删 除 客 户
4 客 户 列 表
5 退 出

请选择(1-5):_
  • 每个客户的信息被保存在Customer对象中。
  • 以一个Customer类型的数组来记录当前所有的客户。
  • 每次“添加客户”(菜单1)后,客户(Customer)对象被添加到数组中。
  • 每次“修改客户”(菜单2)后,修改后的客户(Customer)对象替换数组中原对象。
  • 每次“删除客户”(菜单3)后,客户(Customer)对象被从数组中清除。
  • 执行“客户列表 ”(菜单4)时,将列出数组中所有客户的信息。

“添加客户”的界面及操作过程如下所示:

1
2
3
4
5
6
7
8
9
10
				……
请选择(1-5):1

---------------------添加客户---------------------
姓名:佟刚
性别:男
年龄:35
电话:010-56253825
邮箱:tongtong@atguigu.com
---------------------添加完成---------------------

“修改客户”的界面及操作过程如下所示:

1
2
3
4
5
6
7
8
9
10
11
				……
请选择(1-5):2

---------------------修改客户---------------------
请选择待修改客户编号(-1退出):1
姓名(佟刚):<直接回车表示不修改>
性别(男):
年龄(35):
电话(010-56253825):
邮箱(tongtong@atguigu.com):tongg@atguigu.com
---------------------修改完成---------------------

“删除客户”的界面及操作过程如下所示:

1
2
3
4
5
6
7
				……
请选择(1-5):3

---------------------删除客户---------------------
请选择待删除客户编号(-1退出):1
确认是否删除(Y/N):y
---------------------删除完成---------------------

“客户列表”的界面及操作过程如下所示:

1
2
3
4
5
6
7
8
9
				……
请选择(1-5):4

---------------------------客户列表---------------------------
编号 姓名 性别 年龄 电话 邮箱
1 佟刚 男 45 010-56253825 tong@abc.com
2 封捷 女 36 010-56253825 fengjie@ibm.com
3 雷丰阳 男 32 010-56253825 leify@163.com
-------------------------客户列表完成-------------------------

软件设计结构

该软件由以下三个模块组成:

  • CustomerView为主模块,负责菜单的显示和处理用户操作
  • CustomerList为Customer对象的管理模块,内部用数组管理一组Customer对象,并提供相应的添加、修改、删除和遍历方法,供CustomerView调用
  • Customer为实体对象,用来封装客户信息

enterMainMenu()方法的活动图

键盘访问的实现

项目中提供了CMUtility.java类,可用来方便地实现键盘访问。
该类提供了以下静态方法:

  • public static char readMenuSelection()

用途:该方法读取键盘,如果用户键入’1’-’5’中的任意字符,则方法返回。返回值为用户键入字符。

  • public static char readChar()public static char readChar(char defaultValue)

用途:这两个方法功能相同,均从键盘读取一个字符,并将其作为方法的返回值。
参数defaultValue — 如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。(提示:此方法可在修改客户时调用)

  • public static int readInt()public static int readInt(int defaultValue)

用途:这两个方法功能相同,均从键盘读取一个长度不超过2位的 整数,并将其作为方法的返回值。
参数defaultValue — 如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。

  • public static String readString(int limit)public static String readString(int limit, String defaultValue)

用途:这两个方法功能相同,均从键盘读取一个长度不超过limit的字符串,并将其作为方法的返回值。
参数limit — 指定字符串的最大长度,defaultValue — 如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。

  • public static char readConfirmSelection()

用途:从键盘读取‘Y’或’N’,并将其作为方法的返回值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package com.javami.p2.bean.until;

import java.util.*;
/**
CMUtility工具类:
将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
*/
public class CMUtility {
private static Scanner scanner = new Scanner(System.in);
/**
用于界面菜单的选择。该方法读取键盘,如果用户键入’1’-’5’中的任意字符,则方法返回。返回值为用户键入字符。
*/
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' && c != '5') {
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
/**
从键盘读取一个字符,并将其作为方法的返回值。
*/
public static char readChar() {
String str = readKeyBoard(1, false);
return str.charAt(0);
}
/**
从键盘读取一个字符,并将其作为方法的返回值。
如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
*/
public static char readChar(char defaultValue) {
String str = readKeyBoard(1, true);
return (str.length() == 0) ? defaultValue : str.charAt(0);
}
/**
从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
*/
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;
}
/**
从键盘读取一个长度不超过2位的整数,并将其作为方法的返回值。
如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
*/
public static int readInt(int defaultValue) {
int n;
for (; ; ) {
String str = readKeyBoard(2, true);
if (str.equals("")) {
return defaultValue;
}

try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
从键盘读取一个长度不超过limit的字符串,并将其作为方法的返回值。
*/
public static String readString(int limit) {
return readKeyBoard(limit, false);
}
/**
从键盘读取一个长度不超过limit的字符串,并将其作为方法的返回值。
如果用户不输入字符而直接回车,方法将以defaultValue 作为返回值。
*/
public static String readString(int limit, String defaultValue) {
String str = readKeyBoard(limit, true);
return str.equals("")? defaultValue : str;
}
/**
用于确认选择的输入。该方法从键盘读取‘Y’或’N’,并将其作为方法的返回值。
*/
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;
}
}

程序的实现

第1步

Customer类的设计

  • Customer为实体类,用来封装客户信息
  • 该类封装客户的以下信息:
    • String name :客户姓名
    • char gender :性别
    • int age :年龄
    • String phone:电话号码
    • String email :电子邮箱
      • 提供各属性的get/set方法
      • 提供所需的构造器(可自行确定)

实现Customer类

  • 按照设计要求编写Customer类,并编译
  • Customer 类中临时添加一个main方法中,作为单元测试方法。在方法中创建Customer对象,并调用对象的各个方法,以测试该类是否编写正确。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.javami.p2.bean;

public class Customer {
private String name;// 客户姓名
private char gender;// 性别
private int age;// 年龄
private String phone;// 电话号码
private String email;// 电子邮箱

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public char getGender() {
return gender;
}

public void setGender(char gender) {
this.gender = gender;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public Customer() {
}

public Customer(String name, char gender, int age, String phone, String email) {
this.name = name;
this.gender = gender;
this.age = age;
this.phone = phone;
this.email = email;

}

}

第2步

CustomerList类的设计

  • CustomerListCustomer对象的管理模块,内部使用数组管理一组Customer对象

  • 本类封装以下信息:

    • Customer[] customers:用来保存客户对象的数组
    • int total = 0 :记录已保存客户对象的数量
  • 该类至少提供以下构造器和方法:

    • public CustomerList(int totalCustomer)
    • public boolean addCustomer(Customer customer)
    • public boolean replaceCustomer(int index, Customer cust)
    • public boolean deleteCustomer(int index)
    • public Customer[] getAllCustomers()
    • public Customer getCustomer(int index)
    • public int getTotal()
  • public CustomerList(int totalCustomer)

    • 用途:构造器,用来初始化customers数组
    • 参数:totalCustomer:指定customers数组的最大空间
  • public boolean addCustomer(Customer customer)

    • 用途:将参数customer添加到数组中最后一个客户对象记录之后
    • 参数:customer指定要添加的客户对象
    • 返回:添加成功返回true;false表示数组已满,无法添加
  • public boolean replaceCustomer(int index, Customer cust)

    • 用途:用参数customer替换数组中由index指定的对象
    • 参数:customer指定替换的新客户对象,index指定所替换对象在数组中的位置,从0开始
    • 返回:替换成功返回true;false表示索引无效,无法替换
  • public boolean deleteCustomer(int index)

    • 用途:从数组中删除参数index指定索引位置的客户对象记录
    • 参数: index指定所删除对象在数组中的索引位置,从0开始
    • 返回:删除成功返回true;false表示索引无效,无法删除
  • public Customer[] getAllCustomers()

    • 用途:返回数组中记录的所有客户对象
    • 返回: Customer[] 数组中包含了当前所有客户对象,该数组长度与对象个数相同。
  • public Customer getCustomer(int index)

    • 用途:返回参数index指定索引位置的客户对象记录
    • 参数: index指定所要获取的客户在数组中的索引位置,从0开始
    • 返回:封装了客户信息的Customer对象

实现CustomerList

按照设计要求编写CustomerList类,并编译
CustomerList类中临时添加一个main方法中,作为单元测试方法。
在方法中创建CustomerList对象(最多存放5个客户对象),然后分别用模拟数据调用以下各个方法,以测试各方法是否编写正确:

  • addCustomer()
  • replaceCustomer()
  • deleteCustomer()
  • getAllCustomers()
  • getCustomer()
  • getTotal()

进一步测试以下情况,以验证该类是否编写正确:

  • 调用addCustomer方法,添加至少5个以上客户对象时;
  • 当数组中客户对象数量为0时,仍然调用replaceCustomer方法替换对象;
  • 当数组中客户对象数量为0时,仍然调用deleteCustomer方法删除对象;
  • 对于replaceCustomerdeleteCustomergetCustomer的调用,当参数index的值无效时(例如-1或6);
  • getAllCustomers方法返回的数组长度是否与实际的客户对象数量一致。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package com.javami.p2.bean.service;

import com.javami.p2.bean.Customer;

public class CustomerList {
private Customer[] customers;// 用来保存客户对象的数组
private int total;// 记录已保存客户对象的数量

/**
* 用来初始化customers数组的构造器
* @param totalCustomer:指定数组的长度
*/
public CustomerList(int totalCustomer){
customers = new Customer[totalCustomer];
}

/**
*
* @Description 将指定的客户添加到数组中
* @param customer
* @return true:添加成功 false:添加失败
*/
public boolean addCustomer(Customer customer){
if(total >= customers.length){
return false;
}
customers[total++] = customer;
return true;
}

/**
*
* @Description 修改指定索引位置的客户信息
* @param index
* @param cust
* @return true:修改成功 false:修改失败
*/
public boolean replaceCustomer(int index,Customer cust){
if(index < 0 || index >= total){
return false;
}
customers[index] = cust;
return true;
}

/**
* 删除指定索引位置上的客户
* @Description
* @param index
* @return true:删除成功 false:删除失败
*/
public boolean deleteCustomer(int index){
if(index < 0 || index >= total){
return false;
}
for (int i = index; i < total-1 ; i++){
customers[i] = customers[i+1];
}

//最后有数据的元素需要置空
customers[--total] = null;
return true;
}

/**
*
* @Description 获取所有的客户信息
* @return
*/
public Customer[] getAllCustomers() {
Customer[] custs = new Customer[total];
for(int i = 0;i < total;i++){
custs[i] = customers[i];
}
return custs;
}

/**
*
* @Description 获取指定索引位置上的客户
* @param index
* @return 如果找打了元素,则返回;如果没有找到,则返回null
*/
public Customer getCustomer(int index) {
if(index < 0 || index >= total){
return null;
}
return customers[index];
}

/**
*
* @Description 获取存储的客户的数量
* @return
*/
public int getTotal(){
return total;
}
}

第3步

CustomerView类的设计

  • CustomerView为主模块,负责菜单的显示和处理用户操作

  • 本类封装以下信息:

  • CustomerList customerList = new CustomerList(10);

  • 创建最大包含10个客户对象的CustomerList 对象,供以下各成员方法使用。

  • 该类至少提供以下方法:

    • public void enterMainMenu()
    • private void addNewCustomer()
    • private void modifyCustomer()
    • private void deleteCustomer()
    • private void listAllCustomers()
    • public static void main(String[] args)
  • public void enterMainMenu()

    • 用途:显示主菜单,响应用户输入,根据用户操作分别调用其他相应的成员方法(如addNewCustomer),以完成客户信息处理。
  • private void addNewCustomer()

  • private void modifyCustomer()

  • private void deleteCustomer()

  • private void listAllCustomers()

    • 用途:这四个方法分别完成“添加客户”、“修改客户”、“删除客户”和“客户列表”等各菜单功能。
    • 这四个方法仅供enterMainMenu()方法调用。
  • public static void main(String[] args)

    • 用途:创建CustomerView实例,并调用 enterMainMenu()方法以执行程序。

实现CustomerView类

  • 按照设计要求编写CustomerView类,逐一实现各个方法,并编译
  • 执行main方法中,测试以下功能:
    • 主菜单显示及操作是否正确
    • “添加客户”操作是否正确,给用户的提示是否明确合理;测试当添加的客户总数超过10时,运行是否正确
    • “修改客户”操作是否正确,给用户的提示是否明确合理;
    • “删除客户”操作是否正确,给用户的提示是否明确合理;
    • “客户列表”操作是否正确,表格是否规整;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
package com.javami.p2.bean.ui;

import com.javami.p2.bean.Customer;
import com.javami.p2.bean.service.CustomerList;
import com.javami.p2.bean.until.CMUtility;

public class CustomerView {
private CustomerList customerList = new CustomerList(10);

public CustomerView(){
Customer customer = new Customer("王涛", '男', 23, "13212341234", "wt@gmail.com");
customerList.addCustomer(customer);
}

/**
* 显示《客户信息管理软件》界面的方法
*
* @Description
*/
public void enterMainMenu() {
boolean isFlag = true;
while(isFlag){
System.out.println("\n-----------------客户信息管理软件-----------------\n");
System.out.println(" 1 添 加 客 户");
System.out.println(" 2 修 改 客 户");
System.out.println(" 3 删 除 客 户");
System.out.println(" 4 客 户 列 表");
System.out.println(" 5 退 出\n");
System.out.print(" 请选择(1-5):");

char menu = CMUtility.readMenuSelection();
switch(menu){
case '1':
addNewCustomer();
break;
case '2':
modifyCustomer();
break;
case '3':
deleteCustomer();
break;
case '4':
listAllCustomers();
break;
case '5':
// System.out.println("退出");

System.out.print("确认是否退出(Y/N):");
char isExit = CMUtility.readConfirmSelection();
if(isExit == 'Y'){
isFlag = false;

}
// break;
}

}

}

/**
* 添加客户的操作
*
* @Description
*/
private void addNewCustomer() {
System.out.println("---------------------添加客户---------------------");
System.out.print("姓名:");
String name = CMUtility.readString(10);
System.out.print("性别:");
char gender = CMUtility.readChar();
System.out.print("年龄:");
int age = CMUtility.readInt();
System.out.print("电话:");
String phone = CMUtility.readString(13);
System.out.print("邮箱:");
String email = CMUtility.readString(30);

//将上述数据封装到对象中
Customer customer = new Customer(name, gender, age, phone, email);
boolean isSuccess = customerList.addCustomer(customer);
if(isSuccess){
System.out.println("---------------------添加完成---------------------");
}else{
System.out.println("-------------------客户目录已满,添加失败---------------");
}
}

/**
* 修改客户的操作
*
* @Description
*/
private void modifyCustomer() {
// System.out.println("修改客户的操作");

System.out.println("---------------------修改客户---------------------");
Customer cust ;
int number;
for(;;){
System.out.print("请选择待修改客户编号(-1退出):");
number = CMUtility.readInt();

if(number == -1){
return;
}

cust = customerList.getCustomer(number - 1);
if(cust == null){
System.out.println("无法找到指定客户!");
}else{//找到了相应编号的客户
break;

}

}
//修改客户信息
System.out.print("姓名(" + cust.getName() + "):");
String name = CMUtility.readString(10, cust.getName());
System.out.print("性别(" + cust.getGender() + "):");
char gender = CMUtility.readChar(cust.getGender());
System.out.print("年龄(" + cust.getAge() + "):");
int age = CMUtility.readInt(cust.getAge());
System.out.print("电话(" + cust.getPhone() + "):");
String phone = CMUtility.readString(13, cust.getPhone());
System.out.print("邮箱(" + cust.getEmail()+ "):");
String email = CMUtility.readString(30, cust.getEmail());

Customer newCust = new Customer(name, gender, age, phone, email);

boolean isRepalaced = customerList.replaceCustomer(number - 1, newCust);
if(isRepalaced){
System.out.println("---------------------修改完成---------------------");
}else{
System.out.println("---------------------修改失败---------------------");
}
}

/**
* 删除客户的操作
*
* @Description
*/
private void deleteCustomer() {
// System.out.println("删除客户的操作");
System.out.println("---------------------删除客户---------------------");
int number;
for(;;){
System.out.print("请选择待删除客户编号(-1退出):");
number = CMUtility.readInt();

if(number == -1){
return;
}

Customer customer = customerList.getCustomer(number - 1);
if(customer == null){
System.out.println("无法找到指定客户!");
}else{
break;
}
}

//找到了指定的客户
System.out.print("确认是否删除(Y/N):");
char isDelete = CMUtility.readConfirmSelection();
if(isDelete == 'Y'){
boolean deleteSuccess = customerList.deleteCustomer(number - 1);
if(deleteSuccess){
System.out.println("---------------------删除完成---------------------");
}else{
System.out.println("---------------------删除失败---------------------");
}
}else{
return;
}
}

/**
* 显示客户列表的操作
*
* @Description
*/
private void listAllCustomers() {
// System.out.println("显示客户列表的操作");
System.out.println("---------------------------客户列表---------------------------\n");

int total = customerList.getTotal();
if(total == 0){
System.out.println("没有客户记录!");

}else{
System.out.println("编号\t姓名\t性别\t年龄\t电话\t\t邮箱");
Customer[] custs = customerList.getAllCustomers();
for(int i = 0;i < custs.length;i++){
Customer cust = custs[i];
System.out.println((i + 1) + "\t" + cust.getName() +
"\t" + cust.getGender() + "\t" + cust.getAge() +
"\t" + cust.getPhone() + "\t" + cust.getEmail());
}
}


System.out.println("-------------------------客户列表完成-------------------------");
}

public static void main(String[] args) {
CustomerView view = new CustomerView();
view.enterMainMenu();
}

}

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!