图书系统(新)
文章目录
- 一. 模式
- (一)单例模式
- (1)饿汉式单例模式
- 1. 定义
- 2. 代码
- (2)懒汉式单例模式
- 1. 定义
- 2. 代码
- (二)工厂模式
- (三)代理模式
- 二. 图书系统框架
- (一)user
- (1)Root
- (2)NormalUser
- (3)相同方法
- (4)引入工厂模式
- 1. IUserFactory
- 2. RootFactory
- 3. NormalFactory
- (5)引入代理模式
- (二)book
- (1)Book
- (2)AnalyzingBook
- (3)Library
- (4)BorrowedUidAndBookId
- (5)AnalyzingBorrowedBook
- (6)再谈NormalUser
- 三. 方法实现
- (一)管理员方法
- (1)addBook
- 1. proxyUser中
- 2. Root中
- 3. Library中
- (2)updateBook
- 1. proxyUser中
- 2. Root中
- 3. Library中
- (3)removeBook
- 1. proxyUser中
- 2. Root中
- 3. Library中
- (4)borrowCount
- 1. proxyUser中
- 2. Root中
- 3. Library中
- (5)generateBook
- 1. proxyUser中
- 2. Root中
- 3. Library中
- 4. Book中
- (6)checkInventoryStatus
- 1. ProxyUser中
- 2. Root中
- 3. Library中
- (7)checkAndRemoveOldBooks
- 1. ProxyUser中
- 2. Root中
- 3. Library中
- (二)普通用户方法
- (8)borrowBook
- 1. ProxyUser中
- 2. NormalUser
- 3. Library中
- (9)returnBook
- 1. proxyUser
- 2. NormalUser
- 3. Library中
- (10)viewBorrowHistory
- 1. proxyUser
- 2. NormalUser
- (三)共同方法
- (11)searchBook
- (12)exit
- (13)displayBooks
- (14)start
- 四. 总结
一. 模式
(一)单例模式
一个类有且只有一个实例对象,所以这就需要我们不能在别的类调用单例类的构造方法,于是可以将构造方法私有化,那么该对象只能通过静态方法来获取
(1)饿汉式单例模式
1. 定义
每次程序运行时都实例化一个对象,不管是否用到,先确保该对象是存在的,即饿汉式单例模式
2. 代码
package single;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 18:27*/
public class Singleton {private static Singleton singleton = new Singleton();private Singleton() {}public static Singleton getInstance() {return singleton;}}
(2)懒汉式单例模式
1. 定义
当需要该类对象的时候,通过类主体来调用静态方法获取该对象并且实例化,而不用时则不会实例化该对象
2. 代码
package single;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 18:36*/
public class Singleton_2 {private static Singleton_2 singleton2;private Singleton_2() {}public Singleton_2 getSingleton2() {if (singleton2 == null) {singleton2 = new Singleton_2();return singleton2;}return singleton2;}
}
(二)工厂模式
创建⼀个专⻔负责创建对象的⼯⼚类,将对象的创建过程封装起来,提供一种来创建对象的方式,可以用一个方法创建出多个用户对象,只需要实例化一个工厂类的对象即可,不需要在同时new多个用户,创建对象与使用对象方法分离,实现低耦合
(三)代理模式
代理模式就是通过代理对象来控制对实际对象的访问,起到一个跳转作用
二. 图书系统框架
(一)user
用户User有管理员Root与普通用户NormalUser,所以抽取Root与NormalUser的共同属性与方法,将User定义为抽象类
定义抽象类属性:
- String name;(名字)
- int ID;(用户id)
- String role;(身份)
- display()(菜单)
- Scanner scanner(输入操作)
(1)Root
root用户对应着管理员的菜单,且role可以写死为**管理员**
package user;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 19:04*/
public class Root extends User{public Root(String name, int ID) {super(name, ID, "管理员");}@Overridepublic int display() {System.out.println("管理员 " + name + " 的操作菜单:");System.out.println("0. 切换角色");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();}//其他操作⽅法//上架图书public void addBook() {}//图书修改 ⽀持修改书名 作者 类别public void updateBook() {}//删除书籍public void removeBook() {}//统计每本书的借阅次数public void borrowCount() {}//查询最受欢迎的前n本书public void generateBook() {}//查看库存状态public void checkInventoryStatus() {}//并移除上架超过⼀年的图书public void checkAndRemoveOldBooks() {}public void exit() {}
}
(2)NormalUser
NormalUser对应着普通用户的菜单,role可以写死为**普通用户**
package user;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 19:05*/
public class NormalUser extends User{public NormalUser(String name, int ID) {super(name, ID, "普通用户");}@Overridepublic int display() {System.out.println("普通⽤⼾ " + name + " 的操作菜单:");System.out.println("0. 切换角色");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();}private void loadBorrowedBook() {}private void storeBorrowedBook() {}//借阅图书public void borrowBook() {}//归还图书public void returnBook() {}// 查看个⼈借阅情况public void viewBorrowBooks() {}}
(3)相同方法
通过比较Root与NormalUser的菜单可以发现,其中前四个方法是一样的,而我们所有的方法最后都是要与图书馆进行交互的,所以我们就可以将前四个方法统一定义到图书馆Library中
(4)引入工厂模式
设置一个接口IUserFactory,设置抽象方法,将抽象类User作为返回值参数为name,ID,再设置两个类,RootFactory与NormalFactory实现该接口,RootFactory来实例化Root对象,NormalFactory实例化NormalUser对象
1. IUserFactory
package factory;import user.User;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 19:40*/
public interface IUserFactory {User createUser(String name, int ID);
}
2. RootFactory
package factory;import user.Root;
import user.User;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 19:41*/
public class RootFactory implements IUserFactory{@Overridepublic User createUser(String name, int ID) {return new Root(name,ID);}
}
3. NormalFactory
package factory;import user.NormalUser;
import user.User;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 19:42*/
public class NormalFactory implements IUserFactory{@Overridepublic User createUser(String name, int ID) {return new NormalUser(name,ID);}
}
(5)引入代理模式
将管理员与普通用户的所有方法放入代理类当中,从而实现代理,代理时,根据用户可以根据用户选择身份的不同来接收不同的对象,从而打印选择不同的菜单
package user;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 20:01*/
public class ProxyUser {private User proxyUser;public ProxyUser(User user) {proxyUser = user;}public User getRealUser() {return proxyUser;}}
(二)book
(1)Book
图书系统中必须要有的就是书
书的属性:
- private int bookId; //书id
private String title; // 书名
private String author; // 作者
private String category; // 类别
private int publishYear; // 出版年份
private boolean isBorrowed; // 借阅状态
private int borrowCount; // 借阅次数
private LocalDate shelfDate; // 上架时间- 其中借阅状态,借阅次数默认就是想要的值,且书的ID我们会设置其自增,所以这三个属性都不用初始化,构造方法去掉这三个属性,我们也不希望普通用户来修改书的属性,所以都私有化,同时提供get与set方法,来供root用户修改提供方法
package book;import java.time.LocalDate;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 20:17*/
public class Book {private int bookId; //书idprivate String title; // 书名private String author; // 作者private String category; // 类别private int publishYear; // 出版年份private boolean isBorrowed; // 借阅状态private int borrowCount; // 借阅次数private LocalDate shelfDate; // 上架时间public Book(String title, String author, String category,int publishYear, LocalDate shelfDate) {this.title = title;this.author = author;this.category = category;this.publishYear = publishYear;this.isBorrowed = false;this.borrowCount = 0;this.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 getPublishYear() {return publishYear;}public void setPublishYear(int publishYear) {this.publishYear = publishYear;}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) {this.shelfDate = shelfDate;}@Overridepublic String toString() {return "Book{" +"bookId=" + bookId +", 书名='" + title + '\'' +", 作者='" + author + '\'' +", 类别='" + category + '\'' +", 出版年份=" + publishYear +", 是否借阅=" + isBorrowed +", 借阅次数=" + borrowCount +", 上架时间=" + shelfDate +'}';}
}
(2)AnalyzingBook
希望将每本书都可以永久保存,这需要用到文件,所以需要专门定义一个类来实现读取书与写书的功能,同时与图书馆library和图书book交互
package book;import com.bit.utils.FileUtils;import java.time.LocalDate;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 20:37*/
public class AnalyzingBook {/*** 将书写入文件* @param books 书的数组* @param filename 要写入的文件名*/public void writeBook(Book[] books, String filename) {// 先遍历书中有效数据int count = 0;for (int i = 0; i < books.length; i++) {if (books[i] != null) {count++;}}StringBuilder stringBuilder = new StringBuilder();// 将书数组的每本信息都转化为字符串for (int i = 0; i < count; i++) {stringBuilder.append(books[i].toStr());if (i != books.length - 1) {// 除了最后一行,将每行都拼接杀那个一个换行符\nstringBuilder.append("\n");}}FileUtils.writeFile(stringBuilder.toString(),filename);}/*** 从文件中读取书* @param filename 文件名* @return 返回书这个数组*/public Book[] loadBook(String filename) {// 判断目前字符串是否为空if (filename == null || filename.isEmpty()) {return null;}// 从文件中读取字符串String file = FileUtils.readFile(filename);// 将字符串以\n分割成一本本书的信息String[] allBook = file.split("\n");Book[] books = new Book[allBook.length];for (int i = 0; i < allBook.length; i++) {books[i] = toBook(allBook[i]);}return books;}/*** 将每一行信息字符串都转化为书* @param file 每一行的书包含的信息字符串* @return 返回的是一本本书*/public Book toBook(String file) {String[] bookFile = file.split(",");// 每个属性进⾏转化赋值int bookId = Integer.parseInt(bookFile[0]);String title = bookFile[1];String author = bookFile[2];String category = bookFile[3];int publishYear = Integer.parseInt(bookFile[4]);boolean isBorrowed = Boolean.parseBoolean(bookFile[5]);int borrowCount = Integer.parseInt(bookFile[6]);LocalDate shelfDate = LocalDate.parse(bookFile[7]);Book book = new Book(title,author,category,publishYear,shelfDate);// 将其他属性设置成读取到的属性book.setBookId(bookId);book.setBorrowed(isBorrowed);book.setBorrowCount(borrowCount);return book;}
}
(3)Library
图书馆是管理书的类,写书与读取书操作都应该与Library类来交互,所以也要在Library中定义两个交互方法,读书(loadBook)与写书(writeBook)
package book;import constant.Constant;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 21:22*/
public class Library {private Book[] books;private AnalyzingBook analyzingBook = new AnalyzingBook();private int bookCount;private static Library library;public static Library getLibrary() {if (library == null) {return new Library();}return library;}private Library() {loadBook();}/*** 读取书籍*/public void loadBook() {Book[] allBook = analyzingBook.loadBook(Constant.ALL_BOOK);books = new Book[Constant.CAPACITY];if (allBook == null) {bookCount = 0;}else {bookCount = allBook.length;if (bookCount > books.length) {books = new Book[bookCount];}for (int i = 0; i < bookCount; i++) {books[i] = allBook[i];}}}public void writeBook() {analyzingBook.writeBook(books,Constant.ALL_BOOK);}}
(4)BorrowedUidAndBookId
借阅书籍时,要保存书籍的id和用户的id,以及用户名字,与上述book时一个性质
package book;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 22:00*/
public class BorrowedUidAndBookId {private int userID;private int bookID;private String name;public BorrowedUidAndBookId() {}public BorrowedUidAndBookId(int userID, int bookID, String name) {this.userID = userID;this.bookID = bookID;this.name = name;}public int getUserID() {return userID;}public void setUserID(int userID) {this.userID = userID;}public int getBookID() {return bookID;}public void setBookID(int bookID) {this.bookID = bookID;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String toStr() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append(userID).append(",");stringBuilder.append(bookID).append(",");stringBuilder.append(name);return stringBuilder.toString();}
}
(5)AnalyzingBorrowedBook
将借阅id写入到文件中,同时与用户类NormalUser和ID类BorrowedUidAndBookId交互
package book;import com.bit.utils.FileUtils;
import constant.Constant;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 22:05*/
public class AnalyzingBorrowedBook {public void writeID(BorrowedUidAndBookId[] ids, String filename) {// 判断当前数组的真是数据int count = 0;for (int i = 0; i < ids.length; i++) {if (ids[i] != null) {count++;}}StringBuilder stringBuilder = new StringBuilder();for (int i = 0; i < count; i++) {stringBuilder.append(ids[i].toStr());if (i != count - 1) {stringBuilder.append("\n");}}FileUtils.writeFile(stringBuilder.toString(), filename);}public BorrowedUidAndBookId[] loadID(String filename) {String file = FileUtils.readFile(filename);if (file == null || file.isEmpty()) {return null;}String[] id = file.split("\n");BorrowedUidAndBookId[] borrowedUidAndBookIds = new BorrowedUidAndBookId[id.length];for (int i = 0; i < id.length; i++) {borrowedUidAndBookIds[i] = toID(id[i]);}return borrowedUidAndBookIds;}private BorrowedUidAndBookId toID(String file) {String[] id = file.split(",");int userID = Integer.parseInt(id[0]);int bookID = Integer.parseInt(id[1]);String name = id[2];BorrowedUidAndBookId borrowedUidAndBookId = new BorrowedUidAndBookId(userID,bookID,name);return borrowedUidAndBookId;}
}
(6)再谈NormalUser
借阅书籍类BorrowedUidAndBookId与普通用户类NormalUser和工具分析类AnalyzingBorrowedBook交互,所以最终落实到普通用户类
package user;import book.AnalyzingBorrowedBook;
import book.BorrowedUidAndBookId;
import book.Library;
import constant.Constant;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 19:05*/
public class NormalUser extends User{private BorrowedUidAndBookId[] borrowedIDS;private static AnalyzingBorrowedBook analyzingBorrowedBook = new AnalyzingBorrowedBook();private int borrowedCount;private Library library = Library.getLibrary();public NormalUser(String name, int ID) {super(name, ID, "普通用户");loadBorrowedBook();}@Overridepublic int display() {System.out.println("普通⽤⼾ " + name + " 的操作菜单:");System.out.println("0. 切换角色");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();}private void loadBorrowedBook() {BorrowedUidAndBookId[] ids = analyzingBorrowedBook.loadID(Constant.BORROWED_BOOK_FILE);borrowedIDS = new BorrowedUidAndBookId[Constant.CAPACITY];if (ids == null) {borrowedCount = 0;}else {borrowedCount = ids.length;if (borrowedCount > borrowedIDS.length) {borrowedIDS = new BorrowedUidAndBookId[borrowedCount];}// 将借阅信息拷贝到borrowedID中for (int i = 0; i < borrowedCount; i++) {borrowedIDS[i] = ids[i];}}}private void storeBorrowedBook() {analyzingBorrowedBook.writeID(borrowedIDS,Constant.BORROWED_BOOK_FILE);}//借阅图书public void borrowBook() {}//归还图书public void returnBook() {}// 查看个⼈借阅情况public void viewBorrowBooks() {}}
三. 方法实现
(一)管理员方法
(1)addBook
添加图书
1. proxyUser中
起到跳转作用
public void addBook() {checkRealUserWhetherAdminUser("你不是root用户!!!");((Root)proxyUser).addBook();}
2. Root中
准备书的信息
//上架图书public void 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(); // 输⼊出版年份scanner.nextLine(); // 吞掉换⾏符LocalDate shelfDate = LocalDate.now(); // 当前时间作为上架时间Book newBook = new Book(title, author, category, year, shelfDate); // 建新书对象//调⽤图书类 添加图书library.addBook(newBook);}
3. Library中
注意一定要写入文件当中
public void addBook(Book newBook) {if (bookCount >= books.length) {grow();}if (bookCount == 0) {newBook.setBookId(1);}else {newBook.setBookId(bookCount+1);}books[bookCount++] = newBook;writeBook();System.out.println("图书 "+newBook.getTitle()+"上架成功!");}
(2)updateBook
更新图书信息
1. proxyUser中
起到跳转作用
//更新书籍操作public void updateBook() {checkRealUserWhetherAdminUser("你不是root用户!!!");((Root)proxyUser).updateBook();}
2. Root中
准备书的信息
//图书修改 ⽀持修改书名 作者 类别public void updateBook() {//1. 先展⽰⼀下⽬前的所有书籍library.displayBooks();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);}
3. Library中
注意一定要写入文件当中
public void updateBook(Book book) {//先找到该书是哪个下标int index = searchByIdReturnIndex(book.getBookId());books[index] = book;System.out.println("图书:" + book.getTitle() +" 更新成功!");//⼀定要进⾏存储writeBook();}
(3)removeBook
删除图书
1. proxyUser中
起到跳转作用
public void removeBook() {checkRealUserWhetherAdminUser("你不是root用户!!!");((Root)proxyUser).removeBook();}
2. Root中
通过id查找是否存在这本书
public void removeBook() {//1. 先展⽰⼀下⽬前的所有书籍library.displayBooks();System.out.println("请输⼊要删除的图书id:");int bookId = scanner.nextInt();scanner.nextLine(); // 吞掉换⾏符Book book = library.searchById(bookId);if (book == null) {System.out.println("没有你要删除的书!");return;}library.removeBook(book);System.out.println("图书:" + book.getTitle() + " 已经删除!");}
3. Library中
在图书馆删除书的信息,然后写入文件当中
public void removeBook(Book book) {loadAllBook();int index = searchByIdReturnIndex(book.getBookId());for (int i = index; i < bookCount - 1; i++) {books[i] = books[i + 1];}books[bookCount - 1] = null;bookCount--;writeBook();}
(4)borrowCount
查看所有图书借阅次数
1. proxyUser中
起到跳转作用,又因为借阅图书和普通用户有关
public void borrowCount( ) {checkRealUserWhetherAdminUser("你不是root用户!!!");((Root)proxyUser).borrowCount();}
2. Root中
因为借阅图书和普通用户及图书馆有关,所以只能跳转到图书馆
public void borrowCount() {library.borrowCount();}
3. Library中
先加载图书,然后在图书馆找书的借阅信息,最后打印出来
public void borrowCount() {loadAllBook();if (bookCount == 0) {System.out.println("没有书籍!");return;}for (int i = 0; i < bookCount; i++) {Book book = books[i];System.out.println("书名:"+book.getTitle()+ " 借阅次数:"+book.getBorrowCount());}}
(5)generateBook
查看最受欢迎的前K本书
1. proxyUser中
起到跳转作用
public void generateBook() {checkRealUserWhetherAdminUser("你不是root用户!!!");((Root)proxyUser).generateBook();}
2. Root中
先让用户输入k的值,k值也应该做限定
public void generateBook() {System.out.println("请输⼊你要查看的最受欢迎的前K本书,注意k值不能超过:"+library.getBookCount());int k = scanner.nextInt();if(k <= 0 || k > library.getBookCount()) {System.out.println("没有最受欢迎的前"+k+"本书!");return;}library.generateBook(k);}
3. Library中
书中的书籍都是按照添加顺序即id排序的,我们不希望打乱该顺序,所以额外申请一个tmp数组,来按照借阅次数排序,这需要book当中实现comparable接口
public void generateBook(int k) {loadAllBook();Book[] tmp = new Book[getBookCount()];for (int i = 0; i < bookCount; i++) {tmp[i] = books[i];}Arrays.sort(tmp);for (int i = 0; i < k; i++) {Book book = tmp[i];System.out.println(" 书名:"+ book.getTitle()+" 作者:"+ book.getTitle()+" 借阅次数:"+book.getBorrowCount());}}
4. Book中
@Overridepublic int compareTo(Book o) {return o.borrowCount - this.borrowCount;}
(6)checkInventoryStatus
查看库存状态
1. ProxyUser中
跳转作用
public void checkInventoryStatus() {checkRealUserWhetherAdminUser("你不是root用户!!!");((Root)proxyUser).checkInventoryStatus();}
2. Root中
跳转作用
3. Library中
打印每本书的借阅状态和名字
public void checkInventoryStatus() {loadAllBook();for (int i = 0; i < bookCount; i++) {Book book = books[i];String status = book.isBorrowed() ? "已借出" : "在馆";System.out.println("书名:"+book.getTitle()+" ⽬前状态:"+status);}}
(7)checkAndRemoveOldBooks
移除上架超过1年的书籍
1. ProxyUser中
跳转作用
public void checkAndRemoveOldBooks() {checkRealUserWhetherAdminUser("你不是root用户!!!");((Root)proxyUser).checkAndRemoveOldBooks();}
2. Root中
跳转作用
public void checkAndRemoveOldBooks() {library.checkAndRemoveOldBooks();}
3. Library中
- 加载书籍信息
- 先获取当前时间戳
long currentTimestamp = System.currentTimeMillis();- 将当前时间转化为LocalDate类型
LocalDate currentDate = Instant.ofEpochMilli(currentTimestamp).atZone(ZoneId.systemDefault()).toLocalDate();- 遍历books数组,获取每本书的LocalDate上架时间
LocalDate specifiedDate = book.getShelfDate();- 按年份比较LocalDate上架时间
long yearsBetween = ChronoUnit.YEARS.between(specifiedDate, currentDate);- 查看相差年份大于1的情况,判断当前书是否被人借阅,被人借阅则不能删除,没有被借阅则可以被删除,但要判断是否删除
if (yearsBetween > 1) {
flag = true;
if (book.isBorrowed()) {
System.out.println(“对不起 " + book.getTitle() + " 正在被借阅,”);
return;
}
System.out.print(“图书 " + book.getTitle() + " 已经上架超过⼀年,是否 移除? (Yes/NO):”);
scanner.nextLine();
String response = scanner.nextLine();
if (response.equalsIgnoreCase(“yes”)) {
removeBook(book);
}
}- 判断是否有书籍大于1年,没有的话给出提示
if (flag) {
return;
}
System.out.println(“没有上架超过⼀年的图书!”);
public void checkAndRemoveOldBooks() {loadAllBook();// 获取当前时间戳long currentTimestamp = System.currentTimeMillis();// 将当前时间戳转换为 LocalDateLocalDate currentDate = Instant.ofEpochMilli(currentTimestamp).atZone(ZoneId.systemDefault()).toLocalDate();boolean flag = 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) {flag = true;if (book.isBorrowed()) {System.out.println("对不起 " + book.getTitle() + " 正在被借阅,");return;}System.out.print("图书 " + book.getTitle() + " 已经上架超过⼀年,是否 移除? (Yes/NO):");scanner.nextLine();String response = scanner.nextLine();if (response.equalsIgnoreCase("yes")) {removeBook(book);}}}if (flag) {return;}System.out.println("没有上架超过⼀年的图书!");}
(二)普通用户方法
(8)borrowBook
借阅书籍,且只能是普通用户才能借阅书籍
1. ProxyUser中
代理NormalUser,跳转作用
public void borrowBook() {checkRealUserWhetherNormalUser("请切换普通用户");((NormalUser)proxyUser).borrowBook();}
2. NormalUser
- 先展示书架的书
- 没有书则不能借阅
- 根据展示来输入要借阅的书的id
- 加载借阅书籍的信息
- 根据id查找该本书,如果没有找到,提示用户,并且结束进程
- 如果有该本书,那么先查找该本书的借阅信息,查看该本书是否被借阅过
- 如果被借阅过那么要判断是被自己借阅过还是别人借阅过,打印出借阅人的id与名字
- 没有被借阅过,那么开始借阅,跳转到图书馆开始借阅,并且将你的id与名字,以及书的id封装到BorrowedUidAndBookId中
- 写入到BorrowBook中
- 最后提示借阅成功
public void borrowBook() {library.displayBooks();// 没有书不能借阅if (library.getBookCount() == 0) {System.out.println("对不起暑假没有书籍,你不能借阅!!!");return;}// 输入信息System.out.println("请输入你要节约的书籍id:");int bookId = scanner.nextInt();// 查找书籍Book book = library.searchById(bookId);if (book == null) {System.out.println("不好意思没有你要借阅的该书籍!!!");return;}// 加载借阅书籍loadBorrowedBook();// 查看借阅情况,观察有没有被借阅过for (int i = 0; i < borrowedCount; i++) {// 被借阅过了,分两种情况if (borrowedIDS[i].getBookId() == book.getBookId()) {// 被自己借阅过if (ID == borrowedIDS[i].getUserId()) {System.out.println("该书 " + book.getTitle() +" 已经被你节约过!" + "借阅人:" + borrowedIDS[i].getName() + " 你的ID:" + borrowedIDS[i].getUserId());return;}else {System.out.println("该书 " + book.getTitle() +" 已经被别人节约过!" + "借阅人:" + borrowedIDS[i].getName() + " 他的ID:" + borrowedIDS[i].getUserId());return;}}}// 没有被借阅过,那么你可以借阅library.borrowBook(bookId);// 将借阅信息存储到数组中borrowedIDS[borrowedCount++] = new BorrowedUidAndBookId(ID,bookId,name);// 写入到BorrowedUidAndBookId中writeBorrowedBook();System.out.println("借阅书籍 " + book.getTitle() +" 成功!!!");}
3. Library中
- 加载书籍信息
- 根据传入的bookId来找到对应书籍
- 将该书籍的isBorrowed改为true
- 写入文件
public void borrowBook(int bookId) {loadAllBook();Book book = searchById(bookId);book.setBorrowed(true);book.incrementBorrowed();writeBook();}
(9)returnBook
归还书籍
1. proxyUser
跳转
public void returnBook() {checkRealUserWhetherNormalUser("请切换普通用户");((NormalUser)proxyUser).returnBook();}
2. NormalUser
- 先加载借阅信息
- 如果借阅次数为0,那么不能归还,结束进程
- 打印当前所有书籍的借阅信息
- 输入要归还的书籍id
- 查找该书,为null则不用归还
- 有这本书,就要查看借阅表中有没有该书
- 遍历借阅表中有这本书,说明该属被借阅了,那么比较借阅id与本人id,相同则可以归还,不相同那么不能归还,说明是别人借的,要打印出借阅人的id与名字,都结束进程
- 归还的时候采用最后一个覆盖该位置信息的方法,将借阅数组最后一个置为null,借阅数量-1,并写入借阅表
- 遍历借阅表结束,都没有结束程序,那么说明这本书,没有被借出去
public void returnBook() {// 加载借阅书籍loadBorrowedBook();// 判断借阅次数if (borrowedCount == 0) {System.out.println("当前没有任何借阅书籍,你不能归还!!!");return;}// 打印借阅情况System.out.println("当前所有的借阅书籍情况如下:");library.disBorrowedStatus();// 输入归还书籍idSystem.out.println("请输入你要归还的书籍id");int bookId = scanner.nextInt();// 查找书籍Book book = library.searchById(bookId);// 为null结束进程if (book == null) {System.out.println("对不起,并没有该书籍!!!");return;}// 遍历借阅表for (int i = 0; i < borrowedCount; i++) {// 借阅表中有这本书if (borrowedIDS[i].getBookId() == bookId) {// 判断是不是自己借阅的这本书if (ID == borrowedIDS[i].getUserId()) {// 可以归还library.returnBook(bookId);System.out.println("归还" + book.getTitle() + "成功!" + "归还人:" + borrowedIDS[i].getName());// 将归还的书从借阅表删除borrowedIDS[i] = borrowedIDS[borrowedCount - 1];// 清空最后一个borrowedIDS[borrowedCount - 1] = null;borrowedCount--;// 写入借阅表writeBorrowedBook();return;}else {System.out.println("对不起, " + book.getTitle() + " 不是你借阅的,你不能归还!!!" + "借阅人是:" + borrowedIDS[i].getName() + " 他的ID:" + borrowedIDS[i].getUserId());return;}}}// 遍历完借阅表,都没有结束进程System.out.println("对不起,这本书没有被借阅哦~~~");}
3. Library中
加载书的信息,根据书的id找到该书,并将该书的isBorrowed置为false,并写入文件
public void returnBook(int bookId) {loadAllBook();Book book = searchById(bookId);book.setBorrowed(false);writeBook();}
(10)viewBorrowHistory
查看个人正在借阅所有书的情况
1. proxyUser
代理,跳转
public void viewBorrowHistory() {checkRealUserWhetherNormalUser("请切换普通用户");((NormalUser)proxyUser).viewBorrowBooks();}
2. NormalUser
- 加载借阅情况
- 如果borrowedCount为0,那么当前没有借阅任何书籍
- 不为0,那么遍历借阅表,打印与自己id相同的借阅书籍,
- 设置一个布尔变量,打印则改变值,来最后判断是否真的借阅了书籍
public void viewBorrowBooks() {loadBorrowedBook();//读取当前借阅所有⽤⼾的借阅书籍的情况System.out.println("您的借阅情况如下:");if (borrowedCount == 0) {System.out.println("对不起,当前借阅表没有任何正在借阅的记录!!!");return;}// 遍历借阅表// 设置一个标记boolean flag = true;for (int i = 0; i < borrowedCount; i++) {// 查找与自己借阅id相同的信息if (borrowedIDS[i].getUserId() == ID) {Book book = library.searchById(borrowedIDS[i].getBookId());System.out.println(book);flag = false;}}if (flag) {System.out.println("对不起,您当前没有正在借阅的书籍!!!");}}
(三)共同方法
(11)searchBook
查找图书,我们设置根据名字来查找,又因为书名可能重复,所以我们遍历数组找
public void searchBook() {loadAllBook();System.out.println("请输⼊你要查找的图书的名称:");String title = scanner.nextLine();boolean flag = true;for (int i = 0; i < bookCount; i++) {if (books[i].getTitle().equalsIgnoreCase(title)) {System.out.println("找到了你要查找的书,书的详细信息如下:");System.out.println(books[i]);flag = false;}}if (flag) {System.out.println("没有你要找的这本书,你查找的书名为:" + title);}}
(12)exit
退出系统的方法
public void exit() {System.out.println("系统已退出。。。");System.exit(0);}
(13)displayBooks
打印当前所有图书,bookCount为0,则说明没有书籍,否则就打印
public void displayBooks() {loadAllBook();System.out.println("当前图书馆当中所有的图书: ");if (bookCount == 0) {System.out.println("当前没有任何图书!!!");return;}for (int i = 0; i < bookCount; i++) {System.out.println(books[i]);}}
(14)start
切换角色的方法,切换角色无非就是重新跳转到生成挑选角色的方法,我们可以把生成角色的方法封装起来,每次调用可以回到最初状态
package start;import factory.IUserFactory;
import factory.NormalFactory;
import factory.RootFactory;
import user.NormalUser;
import user.ProxyUser;
import user.Root;
import user.User;import java.util.Scanner;/*** Created with IntelliJ IDEA.* Description:* User: 32309* Date: 2025-07-17* Time: 19:32*/
public class LibrarySystem {public static void main(String[] args) {start();}public static void start() {IUserFactory rootFactory = new RootFactory();User rootFactoryUser = rootFactory.createUser("然",1001);IUserFactory normalFactory = new NormalFactory();User normalFactoryUser1 = normalFactory.createUser("🤪",1002);User normalFactoryUser2 = normalFactory.createUser("🤡",1003);ProxyUser proxyUser1 = new ProxyUser(rootFactoryUser);ProxyUser proxyUser2 = new ProxyUser(normalFactoryUser1);ProxyUser proxyUser3 = new ProxyUser(normalFactoryUser2);ProxyUser user = getUsers(proxyUser1,proxyUser2,proxyUser3);while (true) {int choice = user.display();user.handleOperation(choice);}}public static ProxyUser getUsers (ProxyUser proxyUser1, ProxyUser proxyUser2,ProxyUser proxyUser3) {ProxyUser user = selectProxyRole(proxyUser1,proxyUser2,proxyUser3);while (user == null) {user = selectProxyRole(proxyUser1,proxyUser2,proxyUser3);}return user;}public static ProxyUser selectProxyRole(ProxyUser proxyUser1, ProxyUser proxyUser2, ProxyUser proxyUser3) {System.out.println("选择⻆⾊进⾏登录:");System.out.println("1.管理员(root)\n2.普通⽤⼾(滑稽🤪)\n3.普通⽤⼾(小丑🤡)\n4.退出系统\n");Scanner scanner = new Scanner(System.in);int choice = scanner.nextInt();switch (choice) {case 1:return proxyUser1;case 2:return proxyUser2;case 3:return proxyUser3;case 4:System.out.println("系统已退出..");System.exit(0);break;default:System.out.println("输入的无效操作,请重新选择:");return null;}return null;}
}
四. 总结
该博客花了小编多天时间,拓展了一两个小功能,希望可以博得你的一个点赞,如果有需要,可以到我的gitee上自取
码云链接:https://gitee.com/jinghua-c/project