Java实战:从零开发图书管理系统
🎁个人主页:User_芊芊君子
🎉欢迎大家点赞👍评论📝收藏⭐文章
🔍系列专栏:【Java】内容概括
【前言】
在学习 JavaSE 的过程中,通过实战项目来巩固知识是非常有效的方式。
图书管理系统
是一个经典的小型项目,它涵盖了Java 面向对象编程、异常处理等多个核心知识点。通过开发这个系统,我们能将零散的知识整合起来,深入理解 Java 程序的设计与开发流程。
文章目录:
- 一、思维导图
- 二、模块设计
- 三、user模块
- 二、book模块
- 五、library模块
- 六、utils模块
- 七、ProxyUser模块
- 七、 业务具体实现
- 1.查找图书,显示图书,退出系统
- 2. 管理员检查权限
- 3.管理员上架图书
- 4.管理员更新图书
- 5.管理员下架图书
- 6.管理员统计每本书的借阅次数
- 7.管理员查询最受欢迎的前n 本书
- 8.管理员查看库存状态
- 9.管理员移除上架超过⼀年的图书
- 10.普通用户检查权限
- 11. 普通用户借阅图书
- 12. 普通用户归还图书
- 13. 普通用户查看当前个人借阅情况
- 八、 LibrarySystem类
一、思维导图
通过思维导图可以更好的理解整个图书系统
二、模块设计
在图书系统中,先设计四大模块:用户,书籍,工具,常量值
三、user模块
在图书管理系统中,用户分为管理员
和普通用户
(不止一个哦),但他们都有这些属性:姓名,ID,角色
- User
public abstract class User {private String name;private int userID;private String role;//用户角色public User(String name, int userID, String role) {this.name = name;this.userID = userID;this.role = role;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getUserID() {return userID;}public void setUserID(int userID) {this.userID = userID;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}/**** @return返回具体选择了什么操作* 1 2 3 4 ...*/public abstract int display();@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", userID=" + userID +", role='" + role + '\'' +'}';}
}
- AdminUser
public class AdminUser extends User{public Scanner scanner;public Library library;public AdminUser(String name, int userID) {super(name, userID, "管理员");scanner = ScannerSingleton.getScannerSingleton();library = Library.getLibrary();}@Overridepublic int display() {System.out.println(" 管理员 " + this.getName() + " 的操作菜单:");System.out.println("1. 查找图书 ");System.out.println("2. 打印所有的图书 ");System.out.println("3. 退出系统 ");System.out.println("4. 上架图书 ");System.out.println("5. 修改图书 ");System.out.println("6. 下架图书 ");System.out.println("7. 统计借阅次数 ");System.out.println("8. 查看最后欢迎的前 K 本书 ");System.out.println("9. 查看库存状态 ");System.out.println("10. 检查超过⼀年未下架的图书 ");System.out.println(" 请选择你的操作: ");return scanner.nextInt();}//其他操作⽅法具体实现...
- NormalUser
public class NormalUser extends User {public Scanner scanner;public Library library;//存储图书借阅信息private PairOfUidAndBookId[] pairOfUidAndBookIds;//当前图书借阅量private int borrowedCount;private final AnalyzingBorrowedBook analyzingBorrowedBook = new AnalyzingBorrowedBook();public NormalUser(String name, int userID) {super(name, userID, "普通用户");loadBorrowedBook();scanner = ScannerSingleton.getScannerSingleton();library = Library.getLibrary();}private void loadBorrowedBook() {PairOfUidAndBookId[] allBorrowedBook;//加载文件借阅信息try {allBorrowedBook = analyzingBorrowedBook.loadObject(Constant.BORROWED_BOOK_MAX_NUM);//默认已借阅图书数组大小为BORROW_BOOK_MAX_NUMpairOfUidAndBookIds = new PairOfUidAndBookId[Constant.BORROW_BOOK_MAX_NUM];//没有读取到已借阅图书if (allBorrowedBook == null) {borrowedCount = 0;} else {//实际数组长度int allBorrowedBookLen = allBorrowedBook.length;//读取超出范围if (allBorrowedBookLen > pairOfUidAndBookIds.length) {//重新分配内存pairOfUidAndBookIds = new PairOfUidAndBookId[allBorrowedBookLen];}//拷贝到已借阅图书数组中for (int i = 0; i < allBorrowedBookLen; i++) {pairOfUidAndBookIds[i] = allBorrowedBook[i];//更新数据borrowedCount = allBorrowedBookLen;}}} catch (IOException e) {throw new RuntimeException(e);}}private void storeBorrowBook() {try {analyzingBorrowedBook.storyObject(pairOfUidAndBookIds, Constant.BORROWED_BOOK_MAX_NUM);} catch (IOException e) {throw new RuntimeException(e);}}@Overridepublic int display() {System.out.println(" 用户 " + this.getName() + " 的操作菜单:");System.out.println("1. 查找图书 ");System.out.println("2. 打印所有的图书 ");System.out.println("3. 退出系统 ");System.out.println("4. 借阅图书 ");System.out.println("5. 归还图书 ");System.out.println("6. 查看当前个人借阅情况 ");System.out.println(" 请选择你的操作: ");return scanner.nextInt();}
//其他操作⽅法具体实现...
- ProxyUser
public class ProxyUser {private User realUser;private Library library;public ProxyUser(User user){this.realUser = user;library = Library.getLibrary();}public int display(){return this.realUser.display();}public int getRealUser() {return this.realUser.display();}//管理员相关方法//普通用户相关方法}
二、book模块
- Book:存放书籍各种属性
public class Book implements Comparable<Book>{//书idprivate int bookId;//书名private String title;//作者private String author;//类别private String category;//出版年份private int publishYearl;//借阅状态private boolean isBorrowed;//借阅次数private int borrowCount;//上架时间private LocalDate ShelfDate;//构造方法,初始化图书对象,id,借阅状态,次数不用传参public Book(String title, String author, String category, int publishYearl, LocalDate shelfDate) {this.title = title;this.author = author;this.category = category;this.publishYearl = publishYearl;ShelfDate = shelfDate;}public int getBookId() {return bookId;}public void setBookId(int bookId) {this.bookId = bookId;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}public int getPublishYearl() {return publishYearl;}public void setPublishYearl(int publishYearl) {this.publishYearl = publishYearl;}public boolean isBorrowed() {return isBorrowed;}public void setBorrowed(boolean borrowed) {isBorrowed = borrowed;}public int getBorrowCount() {return borrowCount;}public void setBorrowCount(int borrowCount) {this.borrowCount = borrowCount;}public LocalDate getShelfDate() {return ShelfDate;}public void setShelfDate(LocalDate shelfDate) {ShelfDate = shelfDate;}//对借阅次数 每次自增1 自减1public void incrementBorrowCount() {this.borrowCount++;}public void decreaseBorrowCount() {this.borrowCount--;}@Overridepublic String toString() {return "Book{" +"bookId=" + bookId +", title='" + title + '\'' +", author='" + author + '\'' +", category='" + category + '\'' +", publishYearl=" + publishYearl +", isBorrowed=" + isBorrowed +", borrowCount=" + borrowCount +", ShelfDate=" + ShelfDate +'}';}
将书籍信息拼接成JSON格式的字符串
public String toJSON(){StringBuilder json = new StringBuilder();json.append(bookId).append(",");json.append(title).append(",");json.append(author).append(",");json.append(category).append(",");json.append(borrowCount).append(",");json.append(isBorrowed).append(",");json.append(borrowCount).append(",");json.append( ShelfDate!= null ? ShelfDate.format(DateTimeFormatter.ISO_LOCAL_DATE) : "null");return json.toString();}
对后期对象的比较做准备
@Overridepublic int compareTo(Book o) {return o.getBorrowCount()-this.getBorrowCount();}
}
五、library模块
- Library类
初始化数组容量,可以放在常量值包中
public class Library {//存储的书籍public Book[] books;//记录当前有效书籍public int bookCount;private static Library library;public Scanner scanner = new Scanner(System.in);private AnalyzingBook analyzingBook = new AnalyzingBook();private Library(){//调用该构造方法时,要加载文件当中的数据到books数组当中//读loadAllBook();}public static Library getLibrary(){if (library == null){library = new Library();}return library;}//写成独立的方法,方便后面实时更新private void loadAllBook() {//读取文件书籍到allBook数组中try {Book[] allBook = analyzingBook.loadObject(Constant.ALL_BOOK_FILE_NAME);// 给当前书架默认分配大小为5books = new Book[Constant.CAPACIYY];if (allBook == null){bookCount = 0;}else {int allBookLen = allBook.length;//5if (allBookLen > books.length){books = new Book[allBookLen];}for (int i = 0; i < allBookLen; i++) {books[i] = allBook[i];}//有效书籍bookCount = allBookLen;}} catch (IOException e) {throw new RuntimeException(e);}}
存储图书到⽂件中
private void storeBook() {try {analyzingBook.storeObject(books,Constant.ALL_BOOK_FILE_NAME);} catch (IOException e) {throw new RuntimeException(e);}}
存储所有图书的文件放在常量值包中
六、utils模块
- AnalyzingBook类
实现文件内容的读取
先将书籍数组对象中每个书籍对象进行字符串的序列号,也就是Book类中的toJSON方法
每本书籍之间使用“
\n
”进行分割把对应书籍组装成书籍对象
public class AnalyzingBook {public void storeObject(Book[] books,String filename) throws IOException {//有效书籍int booksUseLen = 0;for (int i = 0; i < books.length; i++) {if (books[i] != null) {booksUseLen++;}}//使每个属性使用逗号拼接StringBuilder jsonArray = new StringBuilder();for (int i = 0; i < booksUseLen; i++) {if (books[i] != null) {jsonArray.append(books[i].toJSON());if (i != booksUseLen - 1) {jsonArray.append("\n");}}}//把内存中存储的数据写到磁盘上FileUtils.writeFile(jsonArray.toString(),filename);}//从文件读取数据public Book[] loadObject(String filename) throws IOException{//从磁盘的文件中读取数据String content = FileUtils.readFile(filename);if (content == null ||content.isEmpty()){System.out.println("图书馆为空");return null;}//用\n作为分隔符进行字符串分隔String[] bookJsonStrings = content.split("\n");//把对应的字符串“组装”成书籍对象Book[] bookList = new Book[bookJsonStrings.length];for (int i = 0; i < bookJsonStrings.length; i++) {Book book = parseBookJson(bookJsonStrings[i]);bookList[i] = book;}return bookList;}
parseBookJson
方法
- 检查json是否为空
- 使用逗号分隔每个属性的值
- 每个属性进行转化赋值
- 构造书籍对象
//“0,java,baby...”private Book parseBookJson(String json){String[] pairs = json.split(",");int bookId = Integer.parseInt(pairs[0]);String title = pairs[1];String author = pairs[2];String category = pairs[3];int publishYear = Integer.parseInt(pairs[4]);boolean isBorrowed = Boolean.parseBoolean(pairs[5]);int borrowCount = Integer.parseInt(pairs[6]);LocalDate shelfDate = LocalDate.parse(pairs[7]);if (title != null && author != null && category != null && shelfDate !=null) {Book book = new Book(title, author, category, publishYear, shelfDate);book.setBorrowed(isBorrowed);book.setBorrowCount(borrowCount);book.setBookId(bookId);return book;}return null;}//测试public static void main(String[] args) {Book[] books = new Book[4];books[0] = new Book("java", "baby", " 编程 ", 1994, LocalDate.of(2023, 9, 24));books[1] = new Book("mysql", "lisi", " 编程 ", 1999, LocalDate.of(2024, 2, 10));books[2] = new Book("php", "baby", " 编程 ", 2020, LocalDate.of(2023, 9, 23));books[3] = new Book("西游记", " 吴承恩 ", "⼩说 ", 2024, LocalDate.of(2023, 9, 23));AnalyzingBook analyzingBook = new AnalyzingBook();//Alt+Entertry {analyzingBook.storeObject(books,"Constant.ALL_BOOK_FILE_NAME");//将数据读到ret数组里面Book[] ret = analyzingBook.loadObject("Constant.ALL_BOOK_FILE_NAME");for (int i = 0; i < ret.length; i++) {System.out.println(ret[i]);}} catch (IOException e) {throw new RuntimeException(e);}}
}
七、ProxyUser模块
- 判断代理对象是否具有权限
- 调用对应用户的方法进行操作
- 查找图书,显示图书,退出系统这三个功能两种用户都具备,写在Library中,不需要区分
public class ProxyUser {private User realUser;private Library library;public ProxyUser(User user){this.realUser = user;library = Library.getLibrary();}public int display(){return this.realUser.display();}public int getRealUser() {return this.realUser.display();}//管理员相关方法//用户相关方法}
七、 业务具体实现
1.查找图书,显示图书,退出系统
这三个功能两种用户都具备,写在Library中,不需要区分。
使用常量代替case的判断条件,并定义在Constant中
public void handleOperation(int choice) {if(this.realUser instanceof AdminUser){switch (choice){case Constant.SEARCH_BOOK:library.searchBook();break;case Constant.DISPLAY_BOOK:library.displayBook();break;case Constant.EXIT:library.exit();break;case Constant.ADD_BOOK:addBook();break;case Constant.UPDATE_BOOK:updateBook();break;case Constant.REMOVE_BOOK:removeBook();break;case Constant.BORROWED_BOOK_COUNT:borrowCount();break;case Constant.GENERATE_BOOK:generateBook();break;case Constant.CHECK_INVENTORY_STATUS:checkInventoryStatus();break;case Constant.CHECK_AND_REMOVE_OLD_BOOK:checkAndRemoveOldBooks();break;default:System.out.println("⽆效的操作。 ");}}else if (realUser instanceof NormalUser) {//普通⽤⼾操作switch (choice) {case Constant.SEARCH_BOOK:library.searchBook();break;case Constant.DISPLAY_BOOK:library.displayBook();break;case Constant.EXIT:library.exit();case Constant.BORROWED_BOOK:borrowBook();break;case Constant.RETURN_BOOK:returnBook();break;case Constant.VIEW_BORROW_HISTORY_BOOK:viewBorrowHistory();break;default:System.out.println("⽆效的操作。 ");}}}
2. 管理员检查权限
- ProxyUser类
private void checkRealUserWhetherAdminUser(String msg){if(!(this.realUser instanceof AdminUser)){throw new PermissionException(msg);}}
3.管理员上架图书
- ProxyUser类
//上架图书public void addBook() {System.out.println("代理类addBook方法执行了");try {checkRealUserWhetherAdminUser("普通用户没有权限添加书籍");}catch (PermissionException e){e.printStackTrace();}((AdminUser)(this.realUser)).addBook();}
- AdminUser类
//上架图书public void addBook() {System.out.println("Admin类addBook方法执行了");scanner.nextLine();//防止有其他字符影响输入System.out.println(" 请输⼊书名: ");String title = scanner.nextLine(); //输⼊书名System.out.println(" 请输⼊作者: ");String author = scanner.nextLine(); //输⼊作者System.out.println(" 请输⼊类别: ");String category = scanner.nextLine(); //输⼊图书类别System.out.println(" 请输⼊出版年份: ");int year = scanner.nextInt(); //输⼊出版年份LocalDate shelfDate = LocalDate.now();Book book = new Book(title,author,category,year,shelfDate);library.addBook(book);}
- Library类
public void addBook(Book book) {System.out.println("Library类addBook执行了");if (bookCount >= books.length) {System.out.println("图书馆已满,无法上架图书");return;}books[bookCount] = book;Book bookLast = books[bookCount-1];book.setBookId(bookLast.getBookId()-1);storeBook();System.out.println("图书上架成功,名称为:" + book.getTitle());}
4.管理员更新图书
- ProxyUser类
//图书修改⽀持修改书名作者类别public void updateBook() {try {checkRealUserWhetherAdminUser("普通用户没有权限更新书籍");}catch (PermissionException e){e.printStackTrace();}((AdminUser)(this.realUser)).updateBook();}
- AdminUser类
//图书修改⽀持修改书名作者类别public void updateBook() {//展示所有书籍library.displayBook();System.out.println("请输入你要修改的id:");int bookId = scanner.nextInt();scanner.nextLine();Book book = library.searchById(bookId);if (book == null){System.out.println("没有你要找的这本ID的书:"+bookId);return;}System.out.println(" 当前书名:" + book.getTitle());System.out.println(" 请输⼊新的书名:");String newTitle = scanner.nextLine(); //输⼊新的书名System.out.println(" 当前作者: " + book.getAuthor());System.out.println(" 请输⼊新的作者: ");String newAuthor = scanner.nextLine(); //输⼊新的作者System.out.println(" 当前类别: " + book.getCategory());System.out.println(" 请输⼊新的类别: ");String newCategory = scanner.nextLine(); //输⼊新的类别book.setTitle(newTitle);book.setAuthor(newAuthor);book.setCategory(newCategory);library.updateBook(book);}
- Library类
//通过bookId找到对应书籍,没=没有就返回nullpublic Book searchById(int bookId) {loadAllBook();//最新的图书for (int i = 0; i < bookCount; i++) {Book book = books[i];if (book.getBookId() == bookId) {return book;}}return null;}public void updateBook(Book book) {int bookId = book.getBookId();int index = searchByIdReturnIndex(book.getBookId());books[index] = book;if(index == -1){System.out.println("没有你要更新的图书,此时Id为:"+bookId);return;}books[index] = book;storeBook();//更新数据System.out.println("书籍已被更新,文件已被写入,更新之后书籍为:");System.out.println(books[index]);}private int searchByIdReturnIndex(int bookId) {loadAllBook();for (int i = 0; i < bookCount; i++) {Book book = books[i];if (book.getBookId() == bookId){return i;}}return -1;}
5.管理员下架图书
- ProxyUser类
//删除书籍public void removeBook() {try {checkRealUserWhetherAdminUser("普通用户没有权限删除书籍");}catch (PermissionException e){e.printStackTrace();}((AdminUser)(this.realUser)).removeBook();}
- AdminUser类
//删除书籍public void removeBook() {library.displayBook();System.out.println("请输入");int bookId = scanner.nextInt();scanner.nextLine();Book removeBook = library.searchById(bookId);if (removeBook == null){System.out.println("没有你要删除的图书");return;}library.removeBook(bookId);System.out.println(" 图书: "+removeBook.getTitle()+" 已经被删除! ");}
- Library类
public void updateBook(Book book) {int bookId = book.getBookId();int index = searchByIdReturnIndex(book.getBookId());books[index] = book;if(index == -1){System.out.println("没有你要更新的图书,此时Id为:"+bookId);return;}books[index] = book;storeBook();//更新数据System.out.println("书籍已被更新,文件已被写入,更新之后书籍为:");System.out.println(books[index]);}
6.管理员统计每本书的借阅次数
- ProxyUser类
//统计每本书的借阅次数public void borrowCount() {try {checkRealUserWhetherAdminUser("普通用户没有权限查看图书借阅次数");}catch (PermissionException e){e.printStackTrace();}((AdminUser)(this.realUser)).borrowCount();}
- AdminUser类
//统计每本书的借阅次数public void borrowCount() {library.borrowCount();}
- Library类
public void borrowCount() {loadAllBook();for (int i = 0; i < bookCount; i++) {Book book = books[i];System.out.println(" 书名:"+book.getTitle()+ " 借阅次数: "+book.getBorrowCount());}}
7.管理员查询最受欢迎的前n 本书
- ProxyUser类
//查询最受欢迎的前n 本书public void generateBook() {try {checkRealUserWhetherAdminUser("普通用户没有权限查询最受欢迎的前n 本书");}catch (PermissionException e){e.printStackTrace();}((AdminUser)(this.realUser)).generateBook();}
- AdminUser类
//查询最受欢迎的前k 本书public void generateBook() {System.out.println(" 请输⼊你要查看的最受欢迎的前 K 本书 , 注意 k 值不能超 过: "+library.bookCount);int k = scanner.nextInt();if(k<= 0 || k>library.bookCount ){System.out.println("没有最受欢迎的前"+k+"本书");return;}library.generateBook(k);}
- Library类
public void generateBook(int k) {loadAllBook();//把所有书籍放在临时数组,进行排序Book[] tmp = new Book[bookCount];for (int i = 0; i < bookCount; i++) {tmp[i] = books[i];}//开始排序Arrays.sort(tmp);//把前k本书拷贝到新数组Book[] generateBooks = new Book[k];for (int i = 0; i < k; i++) {generateBooks[i] = tmp[i];}//打印新数组System.out.println("最受欢迎书籍:");for (int i = 0; i < generateBooks.length; i++) {Book book = generateBooks[i];System.out.println(" ID: "+book.getBookId()+" 书名: "+ book.getTitle()+" 作者: "+ book.getAuthor()+" 借阅次数: "+book.getBorrowCount());}}
8.管理员查看库存状态
- ProxyUser类
//查看库存状态public void checkInventoryStatus() {try {checkRealUserWhetherAdminUser("普通用户没有权限查看库存状态");}catch (PermissionException e){e.printStackTrace();}((AdminUser)(this.realUser)).checkInventoryStatus();}
- AdminUser类
//查看库存状态public void checkInventoryStatus() {library.checkInventoryStatus();}
- Library类
public void checkInventoryStatus() {loadAllBook();for (int i = 0; i < bookCount; i++) {Book book = books[i];String status = "未借出";if(book.isBorrowed()){status = "已借出";}System.out.println(" 书名: "+book.getTitle()+"⽬前状态: "+status);}}
9.管理员移除上架超过⼀年的图书
- ProxyUser类
//并移除上架超过⼀年的图书public void checkAndRemoveOldBooks() {try {checkRealUserWhetherAdminUser("普通用户没有权限移除上架超过⼀年的图书");}catch (PermissionException e){e.printStackTrace();}((AdminUser)(this.realUser)).checkAndRemoveOldBooks();}
- AdminUser类
//并移除上架超过⼀年的图书public void checkAndRemoveOldBooks(){library.checkAndRemoveOldBooks();}
- Library类
public void checkAndRemoveOldBooks() {//移除上架超过⼀年的图书loadAllBook();//获取当前时间戳long currentTimestamp = System.currentTimeMillis();//将当前时间戳转换为LocalDateLocalDate currentDate = Instant.ofEpochMilli(currentTimestamp).atZone(ZoneId.systemDefault()).toLocalDate();boolean flg = false;for (int i = 0; i < bookCount; i++) {Book book = books[i];//获取当前书籍的上架时间LocalDate specifiedDate = book.getShelfDate();//计算两个⽇期之间的差值(以年为单位)long yearsBetween = ChronoUnit.YEARS.between(specifiedDate,currentDate);if(yearsBetween >= 1) {System.out.print(" 图书 " + book.getTitle() + " 已经上架超过⼀年,是否 移除? (y/n): ");scanner.nextLine();String response = scanner.nextLine();if (response.equalsIgnoreCase("y")) {//确认删除调⽤remove⽅法进⾏删除removeBook(book.getBookId());i--; //因为后⾯的书已经向前移动,所以要重新检查当前索引位置}flg = true;}}if(!flg) {System.out.println(" 没有上架超过⼀年的图书! ");}storeBook();}
10.普通用户检查权限
- ProxyUser类
private void checkRealUserWhetherNormalUser(String msg) {if(!(realUser instanceof NormalUser)){throw new PermissionException(msg);}}
11. 普通用户借阅图书
- ProxyUser类
//借阅图书public void borrowBook(){System.out.println("代理类borrowBook方法执行了");checkRealUserWhetherNormalUser("管理员不能借阅图书,请换做普通用户来借阅");((NormalUser)(this.realUser)).borrowBook();}
- NormalUser类
//借阅图书public void borrowBook() {scanner.nextLine();System.out.println("请输入你要借阅的图书id:");int bookId = scanner.nextInt();scanner.nextLine();//如果书架没有书 不能借阅if (library.bookCount == 0) {System.out.println("书架没有书籍暂时不能借阅");return;}//加载已借阅的图书信息loadBorrowedBook();//判断要借阅的书 是否存在Book book = library.searchById(bookId);if (book == null) {System.out.println("没有该id相关书籍:" + bookId);return;}//开始准备借阅图书for (int i = 0; i < borrowedCount; i++) {PairOfUidAndBookId pairOfUidAndBookIds1 = pairOfUidAndBookIds[i];if (pairOfUidAndBookIds1.getBookId() == book.getBookId()) {//getUserID当前用户IDif (pairOfUidAndBookIds1.getBookId() == getUserID()) {System.out.println("这本书自己已经借阅过");return;} else {System.out.println("这本书别人已经借阅过");return;}}}library.boorowBook(bookId);//写入借阅书籍的txtPairOfUidAndBookId pairOfUidAndBookId = new PairOfUidAndBookId(getUserID(), book.getBookId());pairOfUidAndBookIds[borrowedCount%4] = pairOfUidAndBookId;borrowedCount++;storeBorrowBook();System.out.println("借阅书籍成功");}
- Library类
public void boorowBook(int bookId) {loadAllBook();Book book = searchById(bookId);book.setBorrowed(true);book.incrementBorrowCount();storeBook();}
12. 普通用户归还图书
- ProxyUser类
//归还图书public void returnBook(){System.out.println("代理类returnBook方法执行了");checkRealUserWhetherNormalUser("管理员不能归还图书,请换做普通用户来归还");((NormalUser)(this.realUser)).returnBook();}
- NormalUser类
//归还图书public void returnBook(){loadBorrowedBook();if (borrowedCount == 0){System.out.println("目前没有用户借阅过书籍");return;}scanner.nextLine();System.out.println("请输入你要归还的书籍ID:");int bookId = scanner.nextInt();scanner.nextLine();//判断要借阅的书 是否已经被自己借阅过了Book book = library.searchById(bookId);if (book == null){System.out.println("没有该Id相关的书籍:"+bookId);return;}for (int i = 0; i < borrowedCount; i++) {//判断书的ID是否相同if(pairOfUidAndBookIds[i].getBookId() == book.getBookId()){//判断用户IDif(getUserID() == pairOfUidAndBookIds[i].getUserId()){library.returnBook(bookId);System.out.println("图书'" +book.getTitle()+"'已成功归还");//用最后一本书替换归还掉的书pairOfUidAndBookIds[i] = pairOfUidAndBookIds[borrowedCount-1];//清空最后一个pairOfUidAndBookIds[borrowedCount - 1] = null;borrowedCount--;storeBorrowBook();}else {System.out.println("该图书不是你借阅的,无法归还:"+book.getTitle());}return;}}}
- Library类
public void returnBook(int bookId) {loadAllBook();Book book = searchById(bookId);book.setBorrowed(false);book.decreaseBorrowCount();storeBook();}
13. 普通用户查看当前个人借阅情况
- ProxyUser类
//查看当前个人借阅情况public void viewBorrowHistory(){System.out.println("代理类viewBorrowHistory方法执行了");checkRealUserWhetherNormalUser("管理员不能查看图书,请换做普通用户来查看");((NormalUser)(this.realUser)).viewBorrowHistory();}
- NormalUser类
//查看当前个人借阅情况public void viewBorrowHistory(){loadBorrowedBook();System.out.println("借阅情况如下:");if(borrowedCount == 0){System.out.println("目前没有借阅记录");}else {boolean flg = false;for (int i = 0; i < borrowedCount; i++) {//用户id相同时,查看书籍idif(pairOfUidAndBookIds[i].getBookId() == getUserID()){flg = true;Book book = library.searchById(pairOfUidAndBookIds[i].getBookId());System.out.println(book);}}if (!flg){System.out.println("你没有借阅过书籍");}}}
八、 LibrarySystem类
运用的工厂,代理模式,可以参考这篇详解:【Java】设计模式——单例、工厂、代理模式
public class LibrarySystem {public static void main(String[] args) {//工厂模式IUserFactory adminUserFactory = new AdminUserFactory();User adminUser = adminUserFactory.creatUser(" 王先生 ", 1);IUserFactory normalUserFactory = new NormalUserFactory();User normal1 = normalUserFactory.creatUser(" 小白 ", 2);User normal2 = normalUserFactory.creatUser("小飞 ", 3);//代理模式ProxyUser proxyUserAdmin = new ProxyUser(adminUser);ProxyUser proxyUserNormal1 = new ProxyUser(normal1);ProxyUser proxyUserNormal2 = new ProxyUser(normal2);
这里的proxyUserAdmin
,proxyUserNormal1
,proxyUserNormal2
是代理对象,要根据用户的选择,来确定对象
LibrarySystem librarySystem = new LibrarySystem();ProxyUser currentUser = librarySystem.selectProxyRole(proxyUserAdmin,proxyUserNormal1,proxyUserNormal2);while (true){int choice = currentUser.display();//选择choice就执行这个用户的某个操作currentUser.handleOperation(choice);}}
public ProxyUser selectProxyRole(ProxyUser proxyUserAdmin, ProxyUser proxyUsernormal1, ProxyUser proxyUsernormal2) {System.out.println("选择角色进行登录:");System.out.println("1. 管理员\n2.普通⽤⼾(小白)\n3.普通⽤⼾(小⻜)\n4.退出系统 ");ProxyUser currentUser = null;Scanner scanner = new Scanner(System.in);int choice = scanner.nextInt();switch (choice) {case 1:currentUser = proxyUserAdmin;break;case 2:currentUser = proxyUsernormal1;break;case 3:currentUser = proxyUsernormal2;break;case 4:System.exit(0);System.out.println("退出系统了");break;default:break;}return currentUser;}
}
项目执行结果
【总结】
通过图书管理系统的开发,我对 JavaSE 的核心知识点有了更深入的理解:
熟练运用面向对象思想(封装、继承、多态)进行类设计。
理解单例模式、代理模式等设计模式在实际项目中的应用。
提升了调试能力,能快速定位并解决空指针、数组越界等常见异常。 这个项目不仅巩固了JavaSE 知识,也让我体会到软件开发的完整流程,从需求分析、模块设计到编码实现、调试优化,每一步都需要严谨的思考与实践。