具体需求
在管理控制台实现图书管理操作
任务概述
管理员注册or登陆
登陆成功,进行图书管理
- 图书新增
- 图书修改
- 图书删除
- 根据图书名称模糊查找图书
- 查看所有图书 (三种排序)
1.价格从高到低排序
2.价格从低到高排序
3.新旧排序(出版日期排序)
任务过程
- 思考图书对象包含哪些属性
- 使用合理的数据结构存储
- 进行编码(有意识的进行异常处理)
- 测试
思路及代码实现
※第一部分: 管理员注册与登录
一、对象
创建一个pojo包,新建类Manager(管理员)
Manager
- 定义成员变量,并通过setter和getter来赋值和取值
private String name;//用户名
private String password;//密码
/**
* setter和getter设置和获取
* @return
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
- 构造无参和全参的构造方法
/**
* 无参构造方法
*/
public Manager() {
}
/**
* 全参构造方法
*/
public Manager(String name, String password) {
this.name = name;
this.password = password;
}
- equals进行比较
/**
* equals进行比较
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Manager manager = (Manager) o;
return Objects.equals(name, manager.name) &&
Objects.equals(password, manager.password);
}
@Override
public int hashCode() {
return Objects.hash(name, password);
}
二、自定义异常
OutNumberBoundException
创建一个exception包,新建异常OutNumberBoundException
public class OutNumberBoundException extends Throwable {
public OutNumberBoundException(String s) {
super(s);
}
}
三、视图分析
主要负责输入输出的视图交互模块
创建一个view包,新建类ManagerView
ManagerView
- 进入系统和退出系统
/**
* 进入系统
*/
public static void welcome(){
System.out.println("欢迎进入图书管理系统!");
}
/**
* 退出系统
*/
public static void bye(){
System.out.println("感谢使用图书管理系统!");
}
主界面
编写主界面main,通过输入来进入图书管理系统主界面(选择注册or登录)
1.管理员登录
2.管理员注册
0.退出系统由于输入012三位数才有效,其它值均无效,因此可以自定义函数vaildNum来处理输入、捕获异常,
当输入的值不为012或输入为字符时,输出异常并重新输入,因此用while循环进行输入,当输入值符合时break;
返回输入的值
/**
*图书管理系统主界面(选择注册or登录)
*/
public static int main(){
int mainNum = 0;
do{
System.out.println("请选择您要进行的操作:");
System.out.println("1.管理员登录");
System.out.println("2.管理员注册");
System.out.println("0.退出系统");
String s = input.nextLine();
try{
mainNum = validNum(s,0,2);
break;
}catch(NumberFormatException | OutNumberBoundException e){
System.out.println(e.getMessage());
}
}while(true);
return mainNum;
}
- vaildNum处理输入、捕获异常(判断输入是否为数字、是否在有效范围内)
/**
* 判断输入是否为数字、是否在有效范围内
* @param s
* @param begin
* @param end
* @return
* @throws NumberFormatException
* @throws OutNumberBoundException
*/
static int validNum(String s, int begin, int end) throws NumberFormatException, OutNumberBoundException {
try{
int num = Integer.parseInt(s);
if (num < begin || num > end){
throw new OutNumberBoundException("数字的范围必须在" + begin + "和" + end +"之间");
}
return num;
}catch(NumberFormatException e){
throw new NumberFormatException("输入的必须是数字!");
}
}
1.管理员登录界面
编写管理员登录界面,输入登录名和密码,返回包含用户名和密码的Manager对象
- 输入用户信息login
/**
*管理员登录界面,输入用户信息
*/
public static Manager login(){
Manager m = new Manager();
System.out.println("=========管理员登录=========");
System.out.print("登录名:");
String name = input.nextLine();
System.out.print("密码:");
String password = input.nextLine();
m.setName(name);
m.setPassword(password);
return m;
}
2. 管理员注册界面
输入用户名和密码,返回包含新用户名和密码的对象
- 输入注册信息register
/**
*管理员注册
*/
public static Manager register(){
Manager m = new Manager();
System.out.println("=========管理员注册=========");
System.out.print("请输入用户名:");
String name = input.nextLine();
System.out.print("请输入密码:");
String password = input.nextLine();
m.setName(name);
m.setPassword(password);
return m;
}
其它操作
- 输出管理员用户名已存在
/**
* 管理员用户名已存在
*/
public static void isExist(){
System.out.println("用户名已存在!");
}
- 输出管理员用户名不存在
/**
* 管理员用户名不存在
*/
public static void noExist(){
System.out.println("用户名不存在!");
}
- 输出注册成功
/**
* 注册成功
*/
public static void print(){
System.out.println("注册成功!");
}
四、数据存取
主要负责数据处理的模块
创建一个dao包,新建类ManagerDao
ManagerDao
- 初始化用户信息,默认几个用户名和密码
public static Map<String, Manager> managerMap = new HashMap<>();
/**
* 初始化图书管理员数据
*/
public ManagerDao(){
managerMap.put("zs123456",new Manager("张三","zs123456"));
managerMap.put("ls123456",new Manager("李四","ls123456"));
managerMap.put("ww123456",new Manager("王五","ww123456"));
}
- 判断用户名是否存在
/**
* 判断用户名是否存在
*/
public static int isManagerExist(Manager m){
for(Manager m1:managerMap.values()){
if(m.getName().equals(m1.getName())){
return 1;//1代表用户名存在
}
}
return -1;//-1代表用户名不存在
}
- 判断用户名和密码是否匹配
/**
* 判断登录时用户名密码是否正确
*/
public static int login(Manager m){
for (Manager m1:managerMap.values()) {
if(m.getName().equals(m1.getName())){
if(m.getPassword().equals(m1.getPassword())){
System.out.println("登陆成功!");
return 1;//1 登陆成功
}
}
}
System.out.println("用户名或密码错误!请重新输入!");
return -1;//密码错误
}
- 注册,添加管理员的信息
/**
* 添加管理员信息
*/
public static void add(Manager m){
managerMap.put(m.getName(),m);
}
※第二部分:图书管理操作
一、对象
在前面创建的pojo包中新建类Book(书籍)
Book
- 定义成员变量,并通过setter和getter来赋值和取值
private String name;//书名
private Double price;//价格
private Integer year;//出版年
private Integer month;//出版月
/**
* setter和getter设置和获取
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}
public Integer getMonth() {
return month;
}
public void setMonth(Integer month) {
this.month = month;
}
- 构造无参和全参的构造方法
/**
* 无参构造方法
*/
public Book() {
}
/**
* 全参构造方法
*/
public Book(String name, Double price, Integer year, Integer month) {
this.name = name;
this.price = price;
this.year = year;
this.month = month;
}
- 将信息转化为字符串
/**
* 将信息转换为字符串
*/
@Override
public String toString() {
return "《" + name + "》" +
"\t¥" + price +
"\t出版年份:" + year +
"年" + month +
"月";
}
二、自定义异常
即前面自定义的异常:OutNumberBoundException
三、视图分析
主要负责输入输出的视图交互模块
在前面创建的view包中新建类BookView
BookView
图书管理主界面
/**
* 图书管理主界面
*/
public static int bookMain(){
int mainNum = 0;
do{
System.out.println("请选择您要进行的操作:");
System.out.println("1.图书新增");
System.out.println("2.图书修改");
System.out.println("3.图书删除");
System.out.println("4.图书查找");//根据书名
System.out.println("5.查看所有图书");
System.out.println("0.退出登录");
String s = input.nextLine();
try{
mainNum = mView.validNum(s,0,5);
break;
}catch(NumberFormatException | OutNumberBoundException e){
System.out.println(e.getMessage());
}
}while(true);
return mainNum;
}
图书新增
- 通过提示输入新增图书信息
/**
* 图书新增
*/
public static Book add(){
String name;
double price;
int year;
int month;
System.out.println("请输入以下信息:");//输入书名
System.out.print("书名:");
name = input.nextLine();
do {//输入价格,进行异常处理
System.out.print("价格:");
String s = input.nextLine();
try {
price = validPrice(s);
break;
} catch (NumberFormatException | OutNumberBoundException e) {
System.out.println(e.getMessage());
}
}while(true);
do {//输入年份,进行异常处理
System.out.print("出版年份:");
String s = input.nextLine();
try {
year = mView.validNum(s,1900,2021);
break;
} catch (NumberFormatException | OutNumberBoundException e) {
System.out.println(e.getMessage());
}
}while(true);
do {//出入月份,进行异常处理
System.out.print("出版月份:");
String s = input.nextLine();
try {
month = mView.validNum(s,1,12);
break;
} catch (NumberFormatException | OutNumberBoundException e) {
System.out.println(e.getMessage());
}
}while(true);
Book b = new Book();//添加book信息
b.setName(name);
b.setPrice(price);
b.setYear(year);
b.setMonth(month);
return b;
}
- 判断输入的价格是否合法有效
/**
* 判断输入的价格是否有效
*/
static double validPrice(String s) throws NumberFormatException, OutNumberBoundException {
try{
double num = Double.parseDouble(s);
if (num < 0 || num > 10000){
throw new OutNumberBoundException("输入的价格不合理!");
}
return num;
}catch(NumberFormatException e){
throw new NumberFormatException("输入的必须是数字!");
}
}
图书修改
- 输入需要更新的图书的书名,先判断要更新的书籍是否存在,不存在则重新输入
/**
* 图书修改
*/
public static String updateBook(){
String name;
while(true){
System.out.print("请输入要更新的书籍名称:");
name = input.nextLine();
if(bDao.search(name) != null){
return name;
}else{
System.out.println("您要更新的书籍不存在,请重新输入!");
}
}
}
- 根据书名来进行图书信息的修改
public static Book updateInformation(String name){
double price;
int year;
int month;
do {
System.out.print("请输入新的价格:");
String s = input.nextLine();
try {
price = validPrice(s);
break;
} catch (NumberFormatException | OutNumberBoundException e) {
System.out.println(e.getMessage());
}
}while(true);
do {
System.out.print("请输入新的出版年份:");
String s = input.nextLine();
try {
year = mView.validNum(s,1900,2021);
break;
} catch (NumberFormatException | OutNumberBoundException e) {
System.out.println(e.getMessage());
}
}while(true);
do {
System.out.print("请输入新的出版月份:");
String s = input.nextLine();
try {
month = mView.validNum(s,1,12);
break;
} catch (NumberFormatException | OutNumberBoundException e) {
System.out.println(e.getMessage());
}
}while(true);
Book b = new Book();
b.setName(name);
b.setPrice(price);
b.setYear(year);
b.setMonth(month);
return b;
}
图书删除
- 输入要删除的书名
/**
* 图书删除
*/
public static String delete(){
System.out.print("请输入要删除的书名:");
String s = input.nextLine();
return s;
}
- 确认是否删除图书
/**
* 确认图书是否删除
*/
public static int isDelete(){
int num = 1;
do{
System.out.println("是否删除图书?");
System.out.println("1.是");
System.out.println("0.否");
String s = input.nextLine();
try{
num = mView.validNum(s,0,1);
break;
}catch(NumberFormatException | OutNumberBoundException e){
System.out.println(e.getMessage());
}
}while(true);
return num;
}
图书查找
- 输入要查找的书名
/**
* 图书查找
*/
public static String search(){
System.out.print("请输入要查找的书名:");
String s = input.nextLine();
return s;
}
查看所有图书
- 选择图书输出打印的方式,查看所有图书
/**
* 查看所有图书
*/
public static int print(){
int num = 0;
do{
System.out.println("请选择图书的打印输出方式:");
System.out.println("1.价格从高到低排序");
System.out.println("2.价格从低到高排序");
System.out.println("3.出版日期从旧到新排序");
String s = input.nextLine();
try{
num = mView.validNum(s,1,3);
break;
}catch(NumberFormatException | OutNumberBoundException e){
System.out.println(e.getMessage());
}
}while(true);
return num;
}
其它操作
- 打印单条图书信息
/**
* 打印单条图书信息
*/
public static void printOne(Book b){
System.out.println("图书信息如下:");
System.out.println(b);
}
- 输出图书不存在
/**
* 图书不存在
*/
public static void noExist(){
System.out.println("查找的图书不存在!");
}
- 输出操作成功
/**
* 操作成功
*/
public static void success(){
System.out.println("操作成功!");
}
四、数据存取
在前面创建的dao包中新建类BookDao
BookDao
- 数据初始化,默认添加几本书
/**
* 初始化,默认添加几本书
*/
public static ArrayList<Book> book = new ArrayList<>();
public BookDao() {
book.add(new Book("C++ primer(第一版)",89.99,2010,10));
book.add(new Book("C++ primer(第二版)",99.99,2020,10));
book.add(new Book("Java编程思想(第一版)",77.77,2010,6));
book.add(new Book("Java核心技术(第一版)",66.88,2010,2));
book.add(new Book("Java编程思想(第二版)",79.99,2019,6));
book.add(new Book("Java核心技术(第二版)",88.88,2021,2));
}
图书新增
- 将view视图中输入的信息添加至book
/**
* 图书新增
*/
public static void add(Book b){
book.add(b);
}
图书修改
- 修改b1的信息:b2为修改后的新信息,将b1的价格和出版年月修改成新信息
/**
* 图书修改
*/
public static Book update(Book b1,Book b2){
b1.setPrice(b2.getPrice());
b1.setYear(b2.getYear());
b1.setMonth(b2.getMonth());
return b1;
}
图书删除
- 通过view输入要删除的书籍名称,通过名称查找书籍全部信息,进行删除(在test中对图书信息已经经过查找,书籍存在则进行删除)
/**
* 图书删除
*/
public static void delete(String name){
Book b = search(name);//找到书籍名称对应的书籍信息
book.remove(b);//list中的remove方法,删除书籍
}
图书查找
- 通过遍历来模糊查找是否存在输入书名的书籍,有则返回
/**
* 图书查找
*/
public static Book search(String bookName){
for (Book b:book) {
if(bookName.equals(b.getName())){
return b;//如果找到了,返回图书信息
}
}
return null;//没找到,返回null
}
(下面的方法考虑到了重名的图书,但是此次简易版管理系统目前不考虑)
// /**
// * 图书查找(考虑到重名的图书,本系统目前不考虑)
// */
// public static int searchAll(String bookName){
// int num = 0;
// for (Book b:book) {
// if(bookName.equals(b.getName())){
// num ++;//记录书的数量
// bView.printOne(b);//如果找到名称相同的图书,则打印
// }
// }
// return num;//返回查找到的图书的数量
// }
查看所有图书
- 获取书籍的信息
/**
* 获取全部book信息
*/
public static ArrayList<Book> getBook(){
return book;
}
- 通过遍历输出全部书籍信息
/**
* 查看所有图书
*/
public static void print(ArrayList<Book> book){
for (Book b:book) {
System.out.println(b);
}
}
价格从高到低排序
/**
* 价格从高到低排序,降序
*/
public static void priceDescendingSort(ArrayList<Book> book){
Collections.sort(book, new PriceDescendingComparator());
print(book);
}
价格从低到高排序
/**
* 价格从低到高排序,升序
*/
public static void priceAscendingSort(ArrayList<Book> book){
Collections.sort(book,new PriceAscendingComparator());
print(book);
}
根据出版日期新旧排序
/**
* 出版日期,从老到新排序
*/
public static void dataAscendingSort(ArrayList<Book> book){
Collections.sort(book,new DataAscendingComparator());
print(book);
}
五、 比较器
新建包comparator,使用比较器接口自定义排序
Comparator的功能和用法可参考文章:Comparable和Comparator接口
价格从高到低排序
- 在comparator包中新建类PriceDescendingComparator 实现Comparator< Book >
public class PriceDescendingComparator implements Comparator<Book> {
@Override
public int compare(Book o1, Book o2) {
int flag = (int)(o1.getPrice() - o2.getPrice());
if(flag < 0) {//o1 < o2(升序)
return 1;//因为想要降序而不是升序,因此不想要o1 < o2,所以要调整顺序,返回1
}else{
return -1;
}
}
}
//tips:可以将return的值理解为是否同意改变当前的顺序
//如果return 1,则调整顺序
//如果return -1,则不调整顺序
价格从低到高排序
- 在comparator包中新建类PriceAscendingComparator实现Comparator< Book >
public class PriceAscendingComparator implements Comparator<Book> {
@Override
public int compare(Book o1, Book o2) {
int flag = (int)(o1.getPrice() - o2.getPrice());
if(flag < 0) {//o1 < o2(升序)
return -1;//因为想要升序,而数据本身已经升序,所以不需要调整顺序,返回-1
}else{
return 1;
}
}
}
//tips:可以将return的值理解为是否同意改变当前的顺序
//如果return 1,则调整顺序
//如果return -1,则不调整顺序
根据出版日期新旧排序
- 在comparator包中新建类PriceAscendingComparator实现Comparator< Book >
public class DataAscendingComparator implements Comparator<Book> {
@Override
public int compare(Book o1, Book o2) {
int flag1 = o1.getYear() - o2.getYear();
int flag2 = o1.getMonth() - o2.getMonth();
if(flag1 < 0) {//o1 < o2(升序)
return -1;//因为想要升序,而数据本身已经升序,所以不需要调整顺序,返回-1
}else if (flag1 > 0){
return 1;
}else{//o1.getYear() == o2.getYear(),年份相同时比较月份
if(flag2 < 0){
return -1;
}else{
return 1;
}
}//end if
}//end compare
}//end class
//tips:可以将return的值理解为是否同意改变当前的顺序
//如果return 1,则调整顺序
//如果return -1,则不调整顺序
※第三部分:图书管理系统控制台
初始界面
/**
* main,管理员登录or注册
* @param args
*/
public static void main(String[] args) {
mView.welcome();
w:while(true){
int menuNum = mView.main();
switch(menuNum) {
case 0://退出系统
break w;//!!!!!attention,这里是退出循环,即退出系统
case 1: //登录,进入用户登录平台
managerLogin();
break w;//!!!!!attention,这里是退出循环
case 2: //注册,进入用户注册平台
managerRegister();
break;!!!!!attention,这里仅仅是退出switch:注册完成之后,选择退出系统或者登录进行图书管理操作,因此这里不退出循环
}
}
mView.bye();
}//end main
注册界面
/**
* 管理员注册界面
*/
static void managerRegister(){
int exist = 1;
do{
Manager m = mView.register();//输入注册的用户信息
exist = mDao.isManagerExist(m);//1用户存在,-1用户不存在
if(exist == 1) {//用户已存在,重新输入
mView.isExist();
continue;
}else{//用户不存在,添加信息
mDao.add(m);
mView.print();//注册成功
break;
}
}while(exist == 1);//输入注册信息,如果用户名存在,则重新输入
}//end managerRegister
登录界面
/**
* 管理员登录界面
*/
static void managerLogin(){
int exist = -1;
int isLogin = 0;
w :do{
Manager m = mView.login(); //输入登录的信息
exist = mDao.isManagerExist(m);//1代表用户名存在,-1代表用户名不存在
if(exist == 1){//用户名存在
isLogin = mDao.login(m);//判断用户名密码是否匹配,输入正确即登陆成功,开始操作
if(isLogin == 1){//登录成功
bookManagement();//进入图书管理界面,
break w;
}else{//用户名或密码错误,重新输入
exist = -1;
}
}else if(exist == -1){
mView.noExist();//用户名不存在
}
}while(exist == -1);//如果用户名不存在,则一直循环输入
}//end managerLogin
图书管理界面
主界面
/**
* 图书管理界面
*/
public static void bookManagement(){
System.out.println("----------------------------------------");
System.out.println("尊敬的管理员,您好!");
w:while(true){
int mainNum = bView.bookMain();//选择需要进行的操作
switch(mainNum){
case 0:{//退出登录
return;
}
case 1:{//1.新增图书
add();
}
break ;
case 2:{//2.修改图书
update();
}
break ;
case 3:{//3.删除图书
delete();
}
break ;
case 4:{//4.查找图书
search();
}
break ;
case 5:{//5.查看所有图书
printAll();
}
break ;
}// end switch
}//end while
}
图书新增
/**
* 图书新增
*/
public static void add(){
while(true){
Book b = bView.add();//输入新增图书的信息
Book b1 = bDao.search(b.getName());//通过书名查找图书是否存在
if(b1 == null){//该书不存在,添加
bDao.add(b);//添加图书
bView.success();
bView.printOne(b);//打印新添加的图书信息
break;
}else{//如果图书已经存在,则重新输入
System.out.println("该图书已存在!请重新输入!");
}
}
}
图书修改
/**
* 图书修改
*/
public static void update(){
String bookName = bView.updateBook();//输入要修改的图书的名称
Book b = bDao.search(bookName);//要修改的图书
bView.printOne(b);//打印要修改的图书的信息
Book b1 = bView.updateInformation(bookName);//输入更新的信息
b1 = bDao.update(b,b1);//进行更新
bView.success();
bView.printOne(b1);//打印输出更新后的该图书信息
}
图书删除
/**
* 图书删除
*/
public static void delete(){
String bookName = bView.delete();//输入要删除的图书name
Book b = bDao.search(bookName);//查找图书,有则返回图书对象
if(b != null){//如果存在该图书,则确认是否删除
if(bView.isDelete() == 1){//确认删除
bDao.delete(b.getName());
System.out.println("删除成功!");
}else{
System.out.println("取消操作成功!");
}
}else{//不存在,则提示输出“不存在”
bView.noExist();
}
}
图书查找
/**
* 图书查找
*/
public static void search(){
String bookName = bView.search();//输入要查找的书名
Book b = bDao.search(bookName);//查找图书
if(b != null){//如果存在该图书,则打印图书信息
bView.printOne(b);
}else{//不存在,则提示输出“不存在”
bView.noExist();
}
}
查看所有图书
/**
* 查看所有图书
*/
public static void printAll(){
int num = bView.print();//选择打印输出的形式
switch(num){
case 1://价格从高到低排序
bDao.priceDescendingSort(bDao.getBook());
break;
case 2://价格从低到高排序
bDao.priceAscendingSort(bDao.getBook());
break;
case 3://出版日期排序,从老到新
bDao.dataAscendingSort(bDao.getBook());
break;
}
}//end printAll