一.初识设计模式
1.单例模式
一般,在类定义后,可以实例化出多个对象。而单例模式是指: 一个类只能实例化出一个对象。常用于对资源有严格限制的场景。
单例模式的实现主要有两种: 饿汉式和懒汉式
1.1 饿汉式
指在程序启动时就直接进行初始化,无论后面是否使用。这样写,可能会造成资源的浪费,但优点是不需要考虑多线程下的线程安全。
1.2 懒汉式
指在使用时才去实例化对象,存在线程不安全的问题,优点是节省了资源。
2.工厂模式
让创建对象和使用对象的过程进行分离。工厂模式专门有一个负责创建对象的工厂类,将创建对象的过程封装,以达到解耦的目的。
工厂模式分为: 简单工厂模式,抽象工厂模式,工厂方法模式,这里采用工厂方法模式。
如下,创建1个管理员对象,2个普通用户对象:
//创建抽象工厂
public interface IUserFactory {
User createrUser(String name, int userId); //用该方法去创建不同工厂的对象
}
//创建Admin工厂
public class AdminFactory implements IUserFactory{
@Override
public User createrUser(String name, int userId) {
return new AdminUser(name,userId);
}
}
//创建Normal工厂
public class NormalFactory implements IUserFactory{
@Override
public User createrUser(String name, int userId) {
return new NormalUser(name,userId);
}
}
//使用工厂生产对象
public static void main(String[] args) {
IUserFactory normalFactory=new NormalFactory();
User normalUser=normalFactory.createrUser("刘备",1);
IUserFactory adminFactory=new AdminFactory();
User adminUser1=adminFactory.createrUser("关羽",2);
User adminUser2=adminFactory.createrUser("张飞",3);
//显然,如果要更改类名,此处也无须变更,因为封装了生产过程
//并且,可以直接创建多个对象,不用多次new
}
3.代理模式
指创建一个代理类来对实际类进行访问。
代理类就像中介,以保证双方可以正常的进行通信。
代理模式可以分为: 静态代理 动态代理 CLIB代理
代理类的定义:
代理类的使用:
被代理对象通过代理类的构造方法传递给真正的用户 realUser,并且每种方法中都必须进行权限检查。
//代理类的定义
public class ProxyUser {
public User realUser;
//由于代理的对象可能有两种,因此使用它们的父类去接收 =》向上转型
public ProxyUser(User realUser) {
this.realUser = realUser;
}
public void addBook(String bookName){
if(realUser instanceof AdminUser)
((AdminUser)realUser).addBook(bookName); //向下转型调用成员方法
else
System.out.println("您没有权限添加图书,请切换为管理员");
}
public void borrowBook(String bookName){
if(realUser instanceof NormalUser)
((NormalUser)realUser).borrowBook(bookName);
else
System.out.println("您没有权限借阅图书,请切换为普通用户");
}
}
public class UserManagement {
public static void main(String[] args) {
IUserFactory adminFactory=new AdminFactory();
User adminUser1=adminFactory.createrUser("刘备",1);
IUserFactory normalFactory=new NormalFactory();
User normalUser1=normalFactory.createrUser("关羽",2);
User normalUser2=normalFactory.createrUser("张飞",3);
//代理类实例化时传入不同的对象
ProxyUser proxyUser=new ProxyUser(adminUser1); //代理管理员对象
//可以调用代理类中的方法,但不一定会允许继续执行
proxyUser.borrowBook("mysql"); //管理员有权调borrowBook
proxyUser.addBook("mysql"); //管理员没有改方法,虽然可以调用,但权限检查不通过,退出执行
}
}
二.模块划分
该项目分为4个模块: 用户模块,书籍模块,工具模块,常量值模块
2.1 User模块
本系统的用户分为两类: 普通用户和管理员。每个用户包含 用户名,用户ID,用户角色三个属性。
User模块的详细划分:
整合到LibraySystem中:
2.2 constant模块
在整个项目当中,会发现有许多大量出现的常量,大量出现意味着如果要修改它们可能会进行大范围的修改,可能会漏掉或者改错,比如写入的文件名。因此使用constant模块来处理这样的常量;
一般,项目中尽可能避免使用常数;
2.3 book模块
2.3.1 book类的定义
book的属性如下:
代码如下:
public class 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、借阅状态和 借阅次数不⽤进⾏参数传递
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;
}
//--------------------------拿到和设置bookId-----------------------------
//--------------------------拿到和设置book书名-----------------------------
//--------------------------拿到和设置book作者-----------------------------
//--------------------------拿到和设置book类别-----------------------------
//--------------------------拿到和设置book出版日期-----------------------------
//--------------------------拿到和设置book借阅状态-----------------------------
//--------------------------拿到和设置book借阅次数-----------------------------
//--------------------------拿到和设置book上架时间-----------------------------
@Override
public String toString() {
return "Book{" +
"bookId='" + bookId + '\'' +
",title='" + title + '\'' +
", author='" + author + '\'' +
", category='" + category + '\'' +
", publishYear=" + publishYear +
", isBorrowed=" + isBorrowed +
", borrowCount=" + borrowCount + ", shelfDate=" + shelfDate +
'}';
}
}
注意点:
- 基本的get,set方法直接可以通过编译器给出
- 构造方法中不包含bookId,因为希望其能在新增书籍时实现自增,而暂时不知道当前Id,故后面设置
- 构造方法中不包含isBorrowed,因为书的默认一定是为借出状态,故不需要初始化
- 构造方法中不包含borrowCount,因此一开始肯定没有借阅次数
2.3 Libary类的设计
2.3.1 总思路
我们希望实现数据的持久化,因此需要将书籍数据存储到mysql,文件等介质中,这里采用的是文件。
整体设计流程为:
2.3.2 工具模块AnalyzingBook
字符串序列化: 将对象转换为字符串。
将Book对象转为字符串,对象的属性间用’,'分割; 将多个Book对象用\n进行分割,最终Book数组转换为字符串,将该字符串写入文件。
进一步说,从文件中读出的是一个字符串,将字符串以\n进行分割,每个部分都是一个Book对象的字符串,字符串以’,'进行分割,之后就可以获得Book对象。
1.将Book对象转为字符串:
//Book类
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(publishYear).append(",");
json.append(isBorrowed).append(",");
json.append(borrowCount).append(",");
json.append(shelfDate!=null?shelfDate.format(DateTimeFormatter.ISO_LOCAL_DATE):null);
return json.toString();
}
2.将数据写入文件:
-
统计Book数组的实际大小
-
遍历数组,首先通过toJson进行序列化,之后添加\n加入下一本书
-
将获得的字符串写入到指定文件
public void storeObject(Book[] books,String filename){ //计算实际有多少本书 int bookLen=0; for(int i=0;i<books.length;i++){ if(books[i]!=null) bookLen++; } //遍历books StringBuilder jsonArray=new StringBuilder(); for(int i=0;i<bookLen;i++){ jsonArray.append(books[i].toJson()); //toJson进行序列化 if(i<bookLen-1) jsonArray.append("\n"); } FileUtils.writeFile(jsonArray.toString(),filename); }
3.将字符串构造为Book对象(解析数据):
public Book parseBookJson(String json){
if(json.isEmpty())
return null;
String[] pairs=json.split(","); //Book对象的字符串以','进行分割
//获得书籍属性
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;
}
4.从文件中读数据:
-
如果文件存在或不为空,将读入的字符串以\n进行分割
-
分割出来的每个部分是一个Book对象的字符串,通过parseBookJson进行构造Book对象
-
返回数据(Book数组)
public Book[] loadObject(String filename){ String content=FileUtils.readFile(filename); //文件不存在||文件无内容 if(content==null||content.isEmpty()){ System.out.println(filename+" is not exist"); return null; } String[] bookString=content.split("\n"); int len=bookString.length; Book[] books=new Book[len]; for(int i=0;i<len;i++) { books[i]=parseBookJson(bookString[i]); } return books; }
2.3.3 Libary类的设计
文件数据读到内存后,经过工具出来后转换为Book数组,因此将其作为成员变量。
public class Libary {
private Book[] books; //书籍数组
private int bookCount; //书的实际数量
private AnalyzingBook analyzingBook=new AnalyzingBook(); //工具类
public Libary() {
//调用构造方法时,初始化books数组,数据来源为工具类中的loadObject方法
}
}
读取文件解析:
private void loadAllBook(){
//将文件的数据读入到allBook临时数组中
Book[] allBook=analyzingBook.loadObject(constant.ALL_BOOK_FILE_NAME);
//书籍数组分配默认大小空间
this.books=new Book[constant.DEFAULT_CAPACITY];
if(allBook==null)
bookCount=0;
else{
int allBookLen= allBook.length;
//如果读入的数据数量>当前书的数量,重新分配大小
if(allBookLen>books.length)
this.books=new Book[allBookLen];
//更新书籍
for(int i=0;i<allBookLen;i++)
this.books[i]=allBook[i];
//更新当前书籍数量
bookCount= allBookLen;
}
}
三.业务逻辑完善
1.ProxyUser类业务完善
ProxyUser中主要的方法: 1.AdiminUser和NormalUser的方法 2.用户交互菜单
1.权限检查: 前面说过,ProxyUser作为代理类,拥有可能成为代理对象的方法,因此对每个方法的访问都需要进行权限检查。
//管理员权限检查
private void checkAdminUser(String msg){
if(!(realUser instanceof AdminUser)){
throw new PermissionException(msg);
}
}
//普通用户权限检查
private void checkNormalUser(String msg){
if(!(realUser instanceof NormalUser)){
throw new PermissionException(msg);
}
}
2.用户交互菜单:
public void handelOperation(int choice){
if(realUser instanceof AdminUser){
switch (choice){
case constant.SEARCH_BOOK:
libary.searchBook();
break;
case constant.DISPLAY_BOOK:
libary.display();
break;
case constant.EXIT:
libary.exit();
break;
case constant.ADD_BOOK:
addBook();
break;
case constant.UPDATE_BOOK:
updateBook();
break;
case constant.DELETE_BOOK:_BOOK:
removeBook();
break;
case constant.BORROW_COUNT:
borrowBook();
break;
case constant.GENERATE_BOOK:
generateBook();
break;
case constant.CHECK_STATUS:
checkInventoryStatus();
break;
case constant.REMOVE_OLD_BOOK:
checkAndRemoveOldBooks();
break;
}
}
else if(realUser instanceof NormalUser){
switch (choice){
case constant.SEARCH_BOOK:
libary.searchBook();
break;
case constant.DISPLAY_BOOK:
libary.display();
break;
case constant.EXIT:
libary.exit();
break;
case constant.BORROW_BOOK:
borrowBook();
break;
case constant.RETURN_BOOK:
returnBook();
break;
case constant.VIEW_STATUS:
viewBorrowHistory();
break;
}
}
}
为了减少数字的使用,用常量来代替,在Constant模块中添加:
//constant类
//---------------------------管理员相关操作--------------------------------
//查找图书
public static final int SEARCH_BOOK=1;
//显示图书
public static final int DISPLAY_BOOK=2;
//退出系统
public static final int EXIT=3;
//上架图书
public static final int ADD_BOOK=4;
//更新图书
public static final int UPDATE_BOOK=5;
//删除图书
public static final int DELETE_BOOK=6;
//查看书籍借阅次数
public static final int BORROW_COUNT=7;
//查看受欢迎的图书
public static final int GENERATE_BOOK=8;
//查看库存状态
public static final int CHECK_STATUS=9;
//移除上架超过1年的书籍
public static final int REMOVE_OLD_BOOK=10;
//---------------------------普通用户相关操作--------------------
//借阅图书
public static final int BORROW_BOOK=4;
//归还图书
public static final int RETURN_BOOK=5;
//查看借阅情况
public static final int VIEW_STATUS=6;
ProxyUser整体的框架:
2.AdminUser类业务完善
AdminUser中,主要完善的是菜单中的相关方法,这些方法的设计直接见源码,不予讨论;
这里,主要对AdminUser的设计进行部分优化;
2.1 单例模式设计Scanner
可以发现,Scanner在多处均被使用,因此在工具模块utils下创建ScannerSingleton工具类,并且将其设计为单例模式;
//utils.ScannerSingleton
public class ScannerSingleton {
private static Scanner sc;
private ScannerSingleton(Scanner sc) {
;
}
public static Scanner getScanner(){
if(sc==null)
sc=new Scanner(System.in);
return sc;
}
}
//AdminUser
private Scanner sc;
public AdminUser(String name, int userId) {
super(name, userId,"管理员");
sc= ScannerSingleton.getScanner();
}
2.2 单例模式设计Libary
我们希望,libary只有1个;
//utils.LibarySingleton
public class LibarySingleton {
private static Libary libary;
private LibarySingleton() {
}
public static Libary getLibary(){
if(libary==null)
libary=new Libary();
return libary;
}
}
//proxyUser
private User realUser;
private Libary libary;
//由于代理的对象可能有两种,因此使用它们的父类去接收 =》向上转型
public ProxyUser(User realUser) {
this.realUser = realUser;
libary= LibarySingleton.getLibary();
}
3.NormalUser类业务完善
NormalUser类中除了各个用户接口,还需要重点考虑的是借阅信息;
当用户借了书后,显然书和用户的信息都要保持,因此用文件存储这些信息;
3.1 PairOfUidAndBookId类
该类主要用于处理借阅信息。
public class PairOfUidAndBookId {
private int userId; //用户ID
private int bookId; //书籍ID
public PairOfUidAndBookId(int userId, int bookId) {
this.userId = userId;
this.bookId = bookId;
}
//get and set
public String toJson(){
StringBuilder str=new StringBuilder();
str.append(userId).append(',');
str.append(bookId);
return str.toString();
}
}
3.2 AnalyingBorrowBook工具类
书籍的借阅信息需要被保存,同时,以后也需要读取这些信息,因此定义工具类AnalyingBorrowBook来进行数据处理;
该工具类与AnalyingBook的思想基本一致;
public class AnalyingBorrowBook {
//读取借阅信息
public PairOfUidAndBookId[] loadObject(String fileName){
String content=FileUtils.readFile(fileName);
if(content==null||content.isEmpty()){
System.out.println("数据不存在");
return null;
}
//拿到每条借阅信息
String[] s=content.split("\n");
PairOfUidAndBookId[] pairOfUidAndBookId=new PairOfUidAndBookId[s.length];
for(int i=0;i<s.length;i++){
//将每条信息构造成PairOfUidAndBookId类对象
String[] tmp=s[i].split(",");
pairOfUidAndBookId[i]=new
PairOfUidAndBookId(Integer.parseInt(tmp[0]),Integer.parseInt(tmp[1]));
}
return pairOfUidAndBookId;
}
//存储借阅信息
public void storeObject(PairOfUidAndBookId[] pairOfUidAndBookIds,String fileName){
StringBuilder str=new StringBuilder();
int n=0;
//统计实际大小
for(int i=0;i<pairOfUidAndBookIds.length;i++){
if(pairOfUidAndBookIds[i]!=null)
n++;
}
for(int i=0;i<n;i++){
if(pairOfUidAndBookIds[i]!=null) {
//借阅信息序列化
str.append(pairOfUidAndBookIds[i].toJson());
if (i != pairOfUidAndBookIds.length - 1)
str.append("\n");
}
}
FileUtils.writeFile(str.toString(),fileName);
}
}
3.3 NormalUser类完善
因为有了借阅书籍的场景,因此对于普通用户其也需要有相关的成员来表示自己的借阅情况
public class NormalUser extends User{
private Scanner scanner;
//User实际借阅次数
private int borrowCount;
//借阅书籍的信息数组
private PairOfUidAndBookId[] borrowBooks;
//借阅书籍的最大容量
public static final int BORROW_BOOK_MAX_NUM=5;
//借阅书籍分析工具
private AnalyingBorrowBook analyingBorrowBook=new AnalyingBorrowBook();
private Libary libary;
public NormalUser(String name, int userId) {
super(name, userId,"普通用户");
scanner=ScannerSingleton.getScanner();
libary=
loadBooks(constant.BORROW_BOOK_FILE_NAME);
}
public void borrowBook(String bookName){
System.out.println("普通用户"+name+"借阅了"+bookName);
}
//读取借阅书籍信息
public void loadBooks() {
PairOfUidAndBookId[] tmpBooks;
tmpBooks = analyingBorrowBook.loadObject(constant.BORROW_BOOK_FILE_NAME);
if (tmpBooks == null)
borrowCount = 0;
else {
int len = tmpBooks.length;
if (len > BORROW_BOOK_MAX_NUM) {
len = BORROW_BOOK_MAX_NUM;
}
borrowBooks = new PairOfUidAndBookId[len];
for (int i = 0; i < len; i++) {
borrowBooks[i] = tmpBooks[i];
}
borrowCount = len;
}
}
//存储书籍信息
public void storeBooks(){
analyingBorrowBook.storeObject(borrowBooks,constant.BORROW_BOOK_FILE_NAME);
}
//普通人员菜单
//归还图书
//借阅图书
//查看个人借阅情况
}
四.管理员端业务的部分实现
1.更新书籍
//ProxyUser类
public void updateBook() {
checkAdminUser("您没有权限执行此操作,请更换权限");
((AdminUser)realUser).updateBook();
}
//AdminUser类
public void updateBook() {
libary.display();
System.out.println("请输入要修改书籍的Id:");
int id=sc.nextInt();
Book book=libary.searchBookId(id);
if(book!=null){
System.out.println("请输入书名:");
String title=sc.nextLine();
System.out.println("请输入作者:");
String author=sc.nextLine();
System.out.println("请输入类别:");
String category=sc.next();
book.setTitle(title);
book.setAuthor(author);
book.setCategory(category);
libary.updateBook(book);
}
else{
System.out.println("该书籍Id不存在!!!");
}
}
//Libary
//判断bookId是否合法
public Book searchBookId(int bookId){
loadAllBook();
for(int i=0;i<bookCount;i++){
if(bookId==books[i].getBookId())
return books[i];
}
return null;
}
//根据bookId返回其在books数组中的index
public int getBooksIndex(int bookId){
loadAllBook();
for(int i=0;i<bookCount;i++){
if(bookId==books[i].getBookId())
return i;
}
return -1;
}
//更新书籍
public void updateBook(Book book) {
//获取书籍在books中的下标
int index=getBooksIndex(book.getBookId());
books[index]=book;
//books数组内容改变,重新将整个数组存入到文件
storeBook();
}
2.删除书籍
//ProxyUser类
public void removeBook() {
checkAdminUser("您没有权限执行此操作,请更换权限");
((AdminUser)realUser).removeBook();
}
//AdminUser类
public void removeBook() {
//打印所有书籍
libary.display();
System.out.println("请输入删除书籍的Id:");
int bookId=sc.nextInt();
sc.nextLine(); //吞掉换行符
//获取要删除书籍的对象
Book book=libary.searchBookId(bookId);
if(book!=null) {
libary.removeBook(bookId);
System.out.println("书籍"+book.getTitle()+"已经成功删除!!!");
}
else
System.out.println("书籍不存在,无法删除");
}
//Libary类
public void removeBook(int bookId){
loadAllBook();
//获取删除书籍的index
int index = getBooksIndex(bookId);
//覆盖书籍
for(int i=index;i<bookCount-1;i++){
books[i]=books[i+1];
}
books[bookCount-1]=null;
//书籍删除,数量减1
bookCount--;
//写回文件
storeBook();
}
3.删除超过上架1年的书籍
//ProxyUser类
public void checkAndRemoveOldBooks() {
checkAdminUser("您没有权限执行此操作,请更换权限");
((AdminUser)realUser).checkAndRemoveOldBooks();
}
//AdminUser类
public void checkAndRemoveOldBooks() {
libary.checkAndRemoveOldBooks();
}
//Libary类
public void checkAndRemoveOldBooks(){
loadAllBook();
//获取时间戳
long currentTime=System.currentTimeMillis();
//转为LocalDate
LocalDate localDate= Instant.ofEpochMilli(currentTime).atZone(ZoneId.systemDefault()).toLocalDate();
boolean flag=false;
for(int i=0;i<bookCount;i++){
//获取书籍的上架时间
LocalDate tmp=books[i].getShelfDate();
//计算时间差值
long yearBetween= ChronoUnit.YEARS.between(localDate,tmp);
//删除书籍
if(yearBetween>=1){
System.out.println("书籍"+books[i].getTitle()+"已经上架超过1年,是否删除?(Y/N)");
scanner.nextLine();
char ch=scanner.nextLine().charAt(0);
if(ch!='N'&&ch!='n')
removeBook(books[i].getBookId());
i--; //由于删除书籍后,后面书籍往前覆盖,因此删除后,i位置仍需要判断,因此i--,循环后i++,继续判断i位置
flag=true;
}
}
if(flag==false)
System.out.println("没有上架超过1年的书籍,删除失败");
}
- Instant.ofEpochMilli(currentTime)是将毫秒级的时间戳转换为Instant对象(UTC时间,正常使用的时间)
- Instant对象根据系统时间转换为带时区的ZonedDateTime对象
- toLocalDate()将ZonedDateTime对象转换为Local
五.普通用户端业务的部分实现
1.借阅书籍
PairOfUidAndBookId类记录了借阅信息,Book类中也包含了借阅信息;
因此如果可以借阅书籍,需要更改 PairOfUidAndBookId数组以及Book中的部分属性;
//ProxyUser类
public void borrowBook() {
checkNormalUser("您没有权限执行此操作,请更换权限");
((NormalUser)realUser).borrowBook();
}
//NormalUser类
public void borrowBook() {
libary.display();
System.out.println("请输入借阅的书籍编号:");
int bookId=scanner.nextInt();
scanner.nextLine();
//检查是否存在书籍
if(libary.getBookCount()==0){
System.out.println("当前没有书籍,无法借阅");
}
//加载借阅书籍信息
loadBooks();
//检查bookId是否合法
Book book=libary.searchBookId(bookId);
if(book==null){
System.out.println("没有符合条件的书籍!!!");
}
//判断该书籍是否已经被借出
for(int i=0;i<borrowCount;i++){
PairOfUidAndBookId pairOfUidAndBookId=borrowBooks[i];
if(pairOfUidAndBookId.getBookId()==book.getBookId()){
if(pairOfUidAndBookId.getUserId()==userId){
System.out.println("您已经借阅过该书籍");
return ;
}
else{
System.out.println("该书籍已被别人借出,用户Id是:"+pairOfUidAndBookId.getUserId());
return ;
}
}
}
//未被借出,则借用
libary.borrowBook(bookId);
//将借阅信息写入借阅数组
PairOfUidAndBookId pairOfUidAndBookId=new PairOfUidAndBookId(userId,book.getBookId());
borrowBooks[borrowCount++]=pairOfUidAndBookId;
//将借阅数组信息写入文件中
storeBooks();
System.out.println("借阅成功!!!");
}
//Libary类
public void borrowBook(int bookId) {
loadAllBook();
for(int i=0;i<bookCount;i++){
//找到借阅书籍
if(books[i].getBookId()==bookId){
books[i].setBorrowed(true);
books[i].incrementBorrowCount();
}
}
storeBook();
}
2.归还书籍
//NormalUser类
public void returnBook() {
loadBooks();
if(borrowCount==0){
System.out.println("当前没有用户借出过书籍");
}
libary.display();
System.out.println("请输入要归还书籍的Id:");
int bookId=scanner.nextInt();
Book book=libary.searchBookId(bookId);
if(book==null){
System.out.println("您输入的Id不合法");
}
//查找借阅的书籍
for(int i=0;i<borrowCount;i++){
if(book.getBookId()==borrowBooks[i].getBookId()){
if(borrowBooks[i].getUserId()!=userId){
System.out.println("您不是该书籍的借阅人,无法借阅");
}
else{
//当是自己借的,删除该位置的借阅信息
//用最后一个元素来覆盖该位置,也可以将后面的元素依次往前覆盖(arr[i]=arr[i+1])
libary.returnBook(bookId);
borrowBooks[i]=borrowBooks[borrowCount-1];
borrowBooks[borrowCount-1]=null;
borrowCount--;
storeBooks();
System.out.println("归还成功!!!");
}
return ;
}
}
System.out.println("您未借阅过该书籍");
}
//Libary类和ProxyUser类的原理均同借阅书籍
六. 总结
以上就是本文所有内容,如果对您有帮助的话就点个赞吧;以上的源码可以在如下码云链接获得:项目链接