今天跟着宋老师将project02敲了一遍,有时候会跟不上老师的思路,会暂停想一会,里面比较绕的地方可能主要就是在交互的时候,再加上可能基础知识运用的不是特别熟练,接下来就将每个类进行分析一波。
Customer类:M
Customer类是这些类中最简单的,其中的构成为五个属性,五个属性对应的get、set方法,以及两个构造器(分别是无参构造和带有所有属性的构造),这个类不用分析。代码如下:
package project02.bean;
/**
*
* @Description Customer类,用来封装客户信息
* @author
* @version
* @date 2021年12月17日下午1:51:09
*/
public class Customer {
//各属性
private String name;
private char gender;
private int age;
private String phone;
private String email;
//get、set方法
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return 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;
}
}
CMUtility类
这个类主要是与键盘输入的交互,判断键盘输入的是否满足要求的数据,是一个简单的工具包,这个工具包我是直接copy下来的。
里面有readKeyBoard方法,这个是封装的,用于CMUtiity类中其他方法的使用,限制输入字符的个数。
readMenuSelection方法是用于获取用户对于功能的选择,该方法就调用了readKeyBoard。
readChar方法是用于读取一个字符的方法,其中在CMUtility中构成了重载,另外一个重载的readChar方法带形参,而形参是默认的字符,通过输入键盘的字符数来进行判断,从而产生结果是默认值还是键入键盘的第一个字符。
readString、readInt方法与readChar方法类似。
readConfirmSelection方法是确认一下自己的选项,主要是用在确认是否退出的选项的
代码如下:
package project02.util;
import java.util.*;
public class CMUtility {
public static void main(String[] args) {
//System.out.println(readMenuSelection());
}
private static Scanner scanner = new Scanner(System.in);
private static String readKeyBoard(int limit,boolean blank){
for (;;) {
String str = scanner.nextLine();
if (str.length()>0 && str.length()<=limit) {
return str;
} else if (blank) {
return str;
}else{
System.out.println("请输入长度不超过"+limit+"的指令");
}
}
}
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' ) {
return c;
} else {
System.out.println("选择错误,请重新输入。");
}
}
}
public static char readChar(){
//获取性别
String str = readKeyBoard(1,false);
return str.charAt(0);
}
public static char readChar(char defaultValue){
//修改性别信息时,不输入信息直接回车
String str = readKeyBoard(1,true);
return (str.length()==0)? defaultValue : str.charAt(0);
}
public static int readInt(){
//获取年龄
int n;
for(;;){
String str = readKeyBoard(2,false);
try{
n = Integer.parseInt(str);
return n;
}catch (NumberFormatException e) {
System.out.println("数字输入错误,请重新输入。");
}
}
}
public static int readInt(int defaultValue){
//修改年龄信息时,不输入信息直接回车
int n;
for(;;){
String str = readKeyBoard(2,true);
if (str.equals("")) {
return defaultValue;
}
try{
n = Integer.parseInt(str);
return n;
}catch (NumberFormatException e) {
System.out.println("数字输入错误,请重新输入。");
}
}
}
public static String readString(int limit){
//姓名、电话、邮箱的输入
return readKeyBoard(limit,false);
}
public static String readString(int limit,String defaultValue){
//修改姓名、电话、邮箱时,不输入信息直接回车
String str = readKeyBoard(limit,true);
return str.equals("") ? defaultValue : str;
}
public static char readConfirmSelection(){
//获取确认的输入
for(;;){
String str = readKeyBoard(1,false).toUpperCase();
char c = str.charAt(0);
if (c=='Y' || c=='N') {
return c;
} else {
System.out.println("选择错误,请输入Y/N");
}
}
}
}
CustomerList类:C
主要是对Customer类进行管理操作
该类的属性:
1.Customer类型的数组customer,用于存放客户的数据,其实本质上是存放每一个客户对象的地址。
2.int类型的total,用于存放客户的数量。
构造器 :带一个形参的构造器CustomerList(int totalCustomer) ,形参是描述了客户的数量,在初始化时便将该类的customer属性进行了初始化大小。
方法:增删改查+获取所有用户+获取用户数量
其中,获取用户数量方法不用说,非常简单,return total即可。
增:形参为要增的对象,增之前要进行判断一下,增加的位置不能超过数组的长度,增加完以后要让total++
删:对于数组这种线性结构来说,删除某一位置的元素,需要后续的元素进行补充,且让原来最后的位置的元素内容变为null,开始先对索引进行判断,索引不能越界 ,不能超过已有的客户的数量即total。需要让从索引位置一直到最后位置依次取后一个的值,其实也是取后一个的地址。对象数组最后位置设置为null,完成删除操作。此处有一注意点:customer[i]=customer[i+1];来取后面的地址时,要让i+1到total,所以for循环的判断条件要是i<total-1。
改:形参为索引和要改成的Customer类型的对象,索引同样不能越界。改的其实是将传入形参的对象的地址赋给数组中索引位置的元素。
查:获取指定位置上的客户内容,开始先对索引进行判断,索引不可越界,如果没越界直接返回对象数组索引位置上的值即可,此处返回的值仍然是一个地址。
获取所有用户:此处新构造了一个对象数组去承接原来的对象数组中的已有的元素,新构造的数组的大小即为total。因为原来的对象数组中并不是每个位置都有客户值,后面没有赋值的为null。遍历新构造的数组便可以得到所有的用户信息。
在此类中,构造器进行初始化时便构造了一个Customer数组类型的customer对象,后续的一些操作都是针对于这个数组而言的,增删改查实际上就是对这个数组的增删改查。
package project02.service;
import project02.bean.Customer;
/**
*
* @Description Customer对象管理模块,负责对Customer对象进行增删改查遍历(数组管理)
* @author
* @version
* @date 2021年12月17日下午1:53:00
*/
public class CustomerList {
//属性
private Customer[] customer;
private int total=0;
//构造器
/**
* 初始化数组customer数组的构造器
* @param totalCustomer
*/
public CustomerList(int totalCustomer) {
customer=new Customer[totalCustomer];
}
//方法
/**
*
* @Description将指定客户添加到数组中
* @author
* @date 2021年12月17日下午2:35:46
* @param customer
* @return 添加成功返回true 添加失败返回 false
*/
public boolean addCustomer(Customer customer)
{ if(total<this.customer.length)
{
this.customer[total++]=customer;
return true;
}else
{
return false;
}
}
/**
*
* @Description 修改指定位置上的客户信息
* @author
* @date 2021年12月17日下午2:43:17
* @param index
* @param cust
* @return true:修改成功 false:修改失败
*/
public boolean replaceCustomer(int index,Customer cust)
{
if(index>0&&index<total)
{
/*
* Scanner sca=new Scanner(System.in); String newName=sca.next(); int
* newAge=sca.nextInt(); String newEmail=sca.next(); String
* newGender=sca.next(); String newPhone=sca.next();
* customer[index].setName(newName); customer[index].setAge(newAge);
* customer[index].setEmail(newEmail);
* customer[index].setGender(newGender.charAt(0));
* customer[index].setPhone(newPhone);
*/
customer[index]=cust;
return true;
}else
{
return false;
}
}
/**
*
* @Description 删除指定位置上的客户
* @author
* @date 2021年12月17日下午3:00:25
* @param index
* @return true:删除成功 false:删除失败
*/
public boolean deleteCustomer(int index)
{
if(index>0&&index<total)
{
for(int i=index;i<total-1;i++) //注意数组的0下标开始
{
customer[i]=customer[i+1];
}
//最后一个有数据的元素需要置为null
customer[total-1]=null;
total--;
return true;
}else
{
return false;
}
}
/**
*
* @Description 获取所有客户信息
* @author
* @date 2021年12月17日下午3:10:39
* @return
*/
public Customer[] getAllCustomers()
{
Customer[] cust=new Customer[total];
for(int i=0;i<cust.length;i++)
{
cust[i]=customer[i]; //复制的是地址值
}
return cust;
}
/**
*
* @Description 获取指定位置上的客户
* @author
* @date 2021年12月17日下午3:14:48
* @return
*/
public Customer getCustomer(int index)
{ if(index<0||index>=total)
{
return null;
}
return customer[index];
}
/**
*
* @Description 获取客户的数量
* @author
* @date 2021年12月17日下午3:17:13
* @return
*/
public int getTotal()
{
return total;
}
}
CustomerView类:V
这是一个主要和用户进行交互的类,其中main函数也是在这个类中,主函数非常简单,在这个类中构建一个这个类的对象,对象调用进入菜单的enterMainMenu()方法。
enterMainMenu()方法:
显示用户界面的信息,通过CMUtility工具包中读入菜单的选择,与项目一相同,还是利用switch对输入的结果进行分类 。
对应于每一个选择进行一个操作。一共有添加客户、修改客户、删除客户、显示客户列表、退出。
其中退出操作不用介绍,提示是否退出,从键盘获取键入的数据,通过键入的数据进行判断是否退出 ,此处,将isFalg作为标识符进行判断 ,从而跳出循环。
添加客户:通过提示以及利用CMUtility工具包进行信息的输入,将输入的信息封装到一个新new的对象中,customerList中的addCustomer方法返回值为boolean类型,通过判断其返回值作为判断是否添加成功。
修改客户:修改客户时可能会出现客户输入的检索索引超出了对象数组中的内容,所以进行一个循环的查找,修改客户的第一步是先找到这个客户,如果找不到,给用户提示信息,如果找到了这个客户,先提示,输入需要修改的客户信息,再输入信息时提示客户修改之前的信息。当输入这些信息以后,创建一个新的对象将刚才输入的数据封装住,再利用customerList类中的改方法进行修改,注意此时改的时候输入的形参一个是原来对象在数组中的位置,此时应是客户输入的数字-1,因为数组都是从0开始的。改命令的返回值也是boolean类型,通过其 返回值判断修改成功还是修改失败。
删除客户:与上述修改客户步骤相同,先找到客户,找到客户再提示用户是否删除,如果删除便调用customerList类中的删方法。删方法返回值也是boolean类型,通过返回值判断是否删除成功。删方法的输入形参同样也是用户输入的数字num-1,原理同上。
显示客户列表:首先检查是否有客户,即看Total的值是否为0,新设变量承接customerList类中的getTotal方法,如果有客户,则调用customerList类中的getAllCustomers()方法,用一个Customer类型的数组承接。此时承接的数组的每一个元素是一个客户对象(但实际上是存的客户对象的地址),通过遍历数组,将数组元素.方法(此时的数组元素是Customer类型,故可以调用Customer类中的get/set方法),从而获得显示客户列表的功能。
代码如下:
package project02.view;
import project02.bean.Customer;
import project02.service.CustomerList;
import project02.util.CMUtility;
/**
*
* @Description 主模块,负责菜单的显示和用户的操作
* @author
* @version
* @date 2021年12月17日下午1:54:47
*/
public class CustomerView {
private CustomerList customerList=new CustomerList(10);
//构造器
public CustomerView()
{
Customer customer=new Customer("james", '男', 37, "13222222222", "james@gmail.com");
customerList.addCustomer(customer);
}
//主函数
public static void main(String[] args) {
CustomerView view =new CustomerView();
view.enterMainMenu();
}
//方法
/**
*
* @Description 显示客户信息管理软件界面方法
* @author
* @date 2021年12月17日下午3:26:28
*/
public void enterMainMenu()
{
boolean isFalg=true;
while(isFalg)
{
System.out.println("\n--------------客户信息管理软件----------------\n");
System.out.println("\t\t 1 添加客户");
System.out.println("\t\t 2 修改客户");
System.out.println("\t\t 3 删除客户");
System.out.println("\t\t 4 客户列表");
System.out.println("\t\t 5 退出\n");
System.out.print("\t 请选择(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.print("确认是否退出(Y/N)");
char isExit=CMUtility.readConfirmSelection();
if(isExit=='Y')
{
isFalg=false;
}
break;
}
}
}
/**
*
* @Description 添加客户操作
* @author
* @date 2021年12月17日下午3:25:08
*/
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==true)
{
System.out.println("--------------添加完成----------");
}else
{
System.out.println("------------客户目录已满,添加失败-------");
}
}
/**
*
* @Description 修改客户操作
* @author
* @date 2021年12月17日下午3:25:30
*/
private void modifyCustomer()
{
System.out.println("------------------修改客户------------");
Customer cust; //声明在外边,在循环中修改,除了循环还可以使用
int num;
while(true)
{
System.out.print("请选择待修改客户的编号(-1退出)");
num = CMUtility.readInt();
if(num==-1)
{
return;
//break;都可
}
cust=customerList.getCustomer(num-1);//此处num-1是因为用户输入1相当于操作数组中的第0个元素
if(cust==null)
{
System.out.println("无法找到指定用户!");
}else//找到了相应的用户
{
break;//跳出while循环
}
}
//修改客户信息
System.out.println("姓名("+cust.getName()+"):");
String name = CMUtility.readString(10, cust.getName());//没有修改还是按照原来的
System.out.println("性别("+cust.getGender()+"):");
char gender = CMUtility.readChar(cust.getGender());
System.out.println("年龄("+cust.getAge()+"):");
int age = CMUtility.readInt(cust.getAge());
System.out.println("电话("+cust.getPhone()+"):");
String phone = CMUtility.readString(13, cust.getPhone());
System.out.println("邮箱("+cust.getEmail()+"):");
String email = CMUtility.readString(30, cust.getEmail());
Customer newCust=new Customer(name, gender, age, phone, email);
boolean isReplaced= customerList.replaceCustomer(num-1, newCust);//此处的num-1是因为用户输入的num-1才是数组中要操作的位置的数
if(isReplaced)
{
System.out.println("--------------修改完成-----------");
}else
{
System.out.println("--------------修改失败-----------");
}
}
/**
*
* @Description删除客户操作
* @author
* @date 2021年12月17日下午3:25:39
*/
private void deleteCustomer()
{
System.out.println("------------------------删除客户--------------");
Customer cust;
int num;
while(true)
{
System.out.print("请选择待删除客户的编号(-1退出)");
num = CMUtility.readInt();
if(num==-1)
{
return;
}
cust = customerList.getCustomer(num-1);//
if(cust==null)
{
System.out.println("无法找到指定客户!");
}else
{
break;
}
}
//找到了指定客户
System.out.print("是否确认删除(Y/N)");
char isDelete = CMUtility.readConfirmSelection();
if(isDelete=='N')
{
return;
}else
{
boolean isDeleteSuccess = customerList.deleteCustomer(num-1);//num-1原理同上相同
if(isDeleteSuccess)
{
System.out.println("-----------------删除成功----------");
}else
{
System.out.println("-----------------删除失败----------");
}
}
}
/**
*
* @Description 显示客户列表操作
* @author
* @date 2021年12月17日下午3:26:10
*/
private void listAllCustomers()
{
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[] allCustomers = customerList.getAllCustomers();
for(int i=0;i<allCustomers.length;i++)
{
System.out.println((i+1)+"\t"
+allCustomers[i].getName()+"\t"
+allCustomers[i].getGender()+"\t"+allCustomers[i].getAge()+"\t"+allCustomers[i].getPhone()+"\t"+allCustomers[i].getEmail());
}
}
System.out.println("-----------------客户列表完成--------\n");
}
}
以上便是这四个类的分析,除去工具类,剩余的三个类正好体现了MVC的编程思想,模型、视图、控制,三者的结合便成为一个小型的项目。
今天 一天都在看、敲和分析这个小项目 ,里面的编程思想确实值得学习,比如说在进行修改时构建一个新的对象,将数组中的地址修改完成修改任务等等,细细品味还是有一些收获的。冲,不能放弃!