当前位置: 首页 > news >正文

重返JAVA之路——图书管理系统

目录

一、功能介绍 

二、设计模块

三、系统构建

1.book模块

2.operation模块

输入循环和验证

 查找图书并处理借阅状态

未找到图书的处理

查找删除图书功能实现

未找到图书的处理

 图书查找与归还

 work方法实现图书信息输出

3. user模块实现

四、主菜单 


一、功能介绍 

功能介绍:
1.实现一个简单的图书管理功能

2.拥有管理员和普通用户两种模式

3.功能:

管理员:

1>查找图书

2>新增图书

3>删除图书

4>显示图书

5>退出系统

普通用户:

1>查找图书

2>借阅图书

3>归还图书

4>退出系统

二、设计模块

我们采用分层设计的思想,将系统分为不同的模块,每个模块负责不同的功能,提高代码的可维护性和可扩展性。主要模块包括:

  • 书籍管理模块:负责图书信息的存储和管理,如图书的添加、删除、查找等操作。
  • 用户管理模块:区分普通用户和管理员用户,为不同用户提供不同的操作菜单。
  • 操作接口模块:定义各种操作的接口,实现具体的操作逻辑,如查找、借阅、归还等。

 book模块

        --Book.java

        --Booklist.java

operation模块

        -- AddOperation.java

        --BorrowedOperation.java

        --DelOperation.java

        --ExitOperation.java

        --FindOperation.java
        --IOPeration.java

        --ReturnOperation.java

        --ShowOperation.java

 user模块

        --AdminUser.java

        --NormalUser.java

        --User.java

        --Main.java

那么,让我们现在就开始这个图书管理系统的构建吧~

三、系统构建

1.book模块

我们首先定义一个名为 Book 的类,用于表示图书对象。该类包含图书的基本信息,如书名、作者、价格、类型以及借阅状态,同时提供了对这些属性的访问和修改方法,并且重写toString 方法以方便打印图书信息。

我们声明一个 Book 类所属的包为 book。在 Java 里,包用于组织类和接口,避免命名冲突。

package book;

然后我们定义一个公共类:(public 表明该类能被其他包中的类访问)。

public class Book {

我们将图书的名称、作者、价格、类型以及借阅状态放进Book类中,并设为私有成员变量。我们使用private 访问修饰符保证这些变量只能在 Book 类内部被访问和修改。

private String name;//书名
private String author;//作者
private int price;//价格
private String type;//类型
private boolean isBorrowed;//借阅状态

 我们在内部类中,创建构造方法用于接收传入的图书的名称、作者、价格和类型。通过构造方法中的this关键字将传入的值赋给对应的成员变量。

public Book(String name, String author, int price, String type) {this.name = name;this.author = author;this.price = price;this.type = type;
}

我们需要知道图书的名称、作者、价格和类型,并且易于修改。使用访问器方法用于获取成员变量的值,修改器方法用于修改成员变量的值。。由于 参数是私有属性,外部类无法直接访问,所以要借助这两个方法来获取和修改它们的值。

   public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getType() {return type;}public void setType(String type) {this.type = type;}
  • getPrice():这是一个 getter 方法,其返回类型为 int,它的功能是返回 price 属性的值。由于 price 是私有属性,外部类无法直接访问,所以要借助这个方法来获取它的值。
  • setPrice(int price):这是一个 setter 方法,它接收一个 int 类型的参数 price,并把该参数的值赋给类的 price 属性。this.price 代表当前对象的 price 属性,这样就能避免局部变量 price 和类的属性 price 产生混淆。
  • getName():这是一个 getter 方法,返回类型为 String,用于返回 name 属性的值。
  • setName(String name):这是一个 setter 方法,接收一个 String 类型的参数 name,并将其赋值给类的 name 属性。
  • getAuthor():这是一个 getter 方法,返回类型为 String,用于返回 author 属性的值。
  • setAuthor(String author):这是一个 setter 方法,接收一个 String 类型的参数 author,并将其赋值给类的 author 属性。
  • getType():这是一个 getter 方法,返回类型为 String,用于返回 type 属性的值。
  • setType(String type):这是一个 setter 方法,接收一个 String 类型的参数 type,并将其赋值给类的 type 属性。

我想要访问和修改图书的借阅状态,这个时候就还需定义两个构造方法,isBorrowed 方法返回图书是否被借出的布尔值,setBorrowed 方法用于设置图书的借阅状态。

public boolean isBorrowed() {return isBorrowed;
}public void setBorrowed(boolean borrowed) {isBorrowed = borrowed;
}

为了能更直观地呈现对象的信息,我们通常会在自定义类中重写 toString() 方法。

toString() 方法重写了 java.lang.Object 类中的 toString() 方法。在 Java 里,Object 类是所有类的父类,也就是说,Java 中的每个类都直接或间接地继承自 Object 类。因此,所有的类都“自带"一个toString() 方法.

  @Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +", type='" + type + '\'' +((isBorrowed == true) ? "  已经被借出":"  未被借出")+/*", isBorrowed=" + isBorrowed +*/'}';}
}

重写之后,当调用 Book 对象的 toString() 方法时,就会返回一个包含 Book 对象详细信息的字符串,从而方便调试、日志记录或者展示对象信息。

 这样我们就完成了Book类的构建,接下来,我们开始构建Booklist类,Booklist 类作为一个图书管理容器,负责存储、初始化和管理图书信息。

我们首先声明 Booklist 类所属的包为 book

package book;

 定义了一个公共类 Booklistpublic 表明该类能被其他包中的类访问。

public class BookList {private Book[] books = new Book[10];private int usedSize;//计数器 来记录 当前实际放的书的书目!public BookList() {//构造方法 来初始化成员this.books[0] = new Book("三国演义","罗贯中",10,"小说");this.books[1] = new Book("西游记","吴承恩",23,"小说");;this.books[2] = new Book("红楼梦","曹雪芹",8,"小说");;this.usedSize = 3;}
  • Books:这是一个 Book 类型的数组,用于存储图书对象。数组的大小被初始化为 10,意味着该图书列表最多可以存储 10 本图书。
  • usedSize:表示当前图书列表中实际存储的图书数量。
  • Booklist 类的构造方法,用于初始化图书列表。在创建 Booklist 对象时,会自动创建三本图书并将它们存储在数组的前三个位置,同时将 usedSize 设置为 3,表示当前图书列表中有 3 本图书。

我们仍然使用访问器和修改器, 获取和修改参数。

//访问和修改图书信息
public Book getBook(int pos) {return Books[pos];
}public void setBook(int pos, Book book) {this.Books[pos] = book;
}public Book[] getBooks() {return Books;
}public void setBooks(Book[] Books) {this.Books = Books;
}// 管理图书数量
public int getUsedSize() {return usedSize;
}public void setUsedSize(int usedSize) {this.usedSize = usedSize;
}
  • getBook(int pos):根据传入的索引位置 pos,返回图书列表中对应位置的 Book 对象。
  • setBook(int pos, Book book):将传入的 Book 对象存储到图书列表的指定位置 pos
  • getBooks():返回整个图书列表数组。
  • setBooks(Book[] Books):将传入的 Book 数组赋值给当前图书列表数组。
  • getUsedSize():返回当前图书列表中实际存储的图书数量。
  • setUsedSize(int usedSize):设置当前图书列表中实际存储的图书数量。

2.operation模块

operation模块中,我们有添加、借阅、删除、退出、查找、归还、显示这些功能。下面我们就为大家逐一讲解。

我们首先需要一个名为 IOPeration 的 Java 接口,为图书管理系统中的各种操作提供一个统一的标准和规范。通过这个接口,不同的操作类(如添加图书、删除图书、查找图书等)可以实现相同的方法,方便在系统中统一调用这些操作。

// IOPeration 
package operation;
import book.Booklist;
import java.util.Scanner;public interface IOPeration {void work(Booklist booklist, Scanner scanner);
}

我们在接口中定义了一个名为 work 的抽象方法。

这个方法接收两个参数:一个是 Booklist 类型的对象 booklist,用于表示图书列表;另一个是 Scanner 类型的对象 scanner,用于从控制台读取用户输入。所有实现 IOPeration 接口的类都必须实现 work 方法。


 下面,我们来创建AddOperation类,用于添加图书的信息。

  • 功能:向 Booklist 中添加一本新图书。
  • 核心逻辑
    • 提示用户输入图书的名称、作者、价格、类型等信息。
    • 创建新的 Book 对象。
    • 将新图书添加到 Booklist 的数组中(需考虑数组是否已满,可能需要动态扩容或提示错误)。
//AddOperation
package operation;import book.Book;
import book.Booklist;
import java.util.Scanner;public class AddOperation implements IOPeration {@Overridepublic void work(Booklist booklist, Scanner scanner) {boolean needInput = true;while (true) {if (needInput) {System.out.println("新增图书!");System.out.println("请输入图书名称:");}String name = scanner.nextLine();if (name == null || name.trim().isEmpty()) {System.out.println("(注意:输入的图书名称不能为空!)");needInput = false; // 此时不需要再提示输入,避免重复continue;}System.out.println("请输入图书作者:");String author = scanner.nextLine();System.out.println("请输入图书价格:");int price = scanner.nextInt();scanner.nextLine(); // 消耗掉换行符System.out.println("请输入图书类型:");String type = scanner.nextLine();Book newBook = new Book(name, author, price, type);int usedSize = booklist.getUsedSize();if (usedSize < booklist.getBooks().length) {booklist.setBook(usedSize, newBook);booklist.setUsedSize(usedSize + 1);System.out.println("图书添加成功!");} else {System.out.println("图书列表已满,无法添加!");}return;}}
}

AddOperation 类实现了 IOPeration 接口,用于添加新的图书。在 work 方法中,通过 Scanner 类从控制台获取用户输入的图书信息,(如书名、作者、价格等),创建一个新的 Book 对象,并将其添加到 booklist (图书列表中)。如果图书列表已满,则提示用户无法添加。


接下来我们创建BorrowedOperation类,用于借阅书籍。

  • 功能:将 Booklist 中的某本图书标记为 “已借出”。
  • 核心逻辑
    • 提示用户输入书名或索引,查找目标图书。
    • 若图书存在且未被借出,将其 isBorrowed 状态设为 true
    • 若图书已被借出或不存在,提示相应错误。
//BorrowedOperation.java
package operation;import book.Book;
import book.Booklist;
import java.util.Scanner;public class BorrowedOperation implements IOPeration {@Overridepublic void work(Booklist booklist, Scanner scanner) {boolean needInput = true;while (true) {if (needInput) {System.out.println("请输入要借阅的图书名称:");}String name = scanner.nextLine();if (name == null || name.trim().isEmpty()) {System.out.println("(请注意:输入的图书名称不能为空!)");needInput = false;continue;}int usedSize = booklist.getUsedSize();for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book.getName().equals(name)) {if (book.isBorrowed()) {System.out.println("该图书已被借出,无法借阅!");} else {book.setBorrowed(true);System.out.println("图书借阅成功!");}return;}}System.out.println("未找到该图书!");return;}}
}

我们来看这段代码: 

输入循环和验证
    boolean needInput = true;
    while (true) {if (needInput) {System.out.println("请输入要借阅的图书名称:");}String name = scanner.nextLine();if (name == null || name.trim().isEmpty()) {System.out.println("(请注意:输入的图书名称不能为空!)");needInput = false;continue;}
    • 我们创建boolean needInput = true;:定义一个布尔变量 needInput,用于控制是否显示输入提示信息。
    • (注意:needInput 变量的主要作用是避免在用户输入为空时重复显示提示信息,以此提升用户体验。不过,该逻辑存在一定局限性,例如当用户连续多次输入空值时,后续就不会再显示输入提示了。)
    • while (true):创建一个无限循环,用于不断提示用户输入图书名称,直到输入有效信息。
    • if (needInput):如果 needInput 为 true,则显示输入提示信息。
    • String name = scanner.nextLine();:从控制台读取用户输入的图书名称。
    • if (name == null || name.trim().isEmpty()):检查用户输入的图书名称是否为 null 或为空字符串(去除前后空格后)。如果是,则显示错误提示信息,将 needInput 设置为 false,并使用 continue 语句跳过本次循环,继续下一次循环。
     查找图书并处理借阅状态
    int usedSize = booklist.getUsedSize();
    for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book.getName().equals(name)) {if (book.isBorrowed()) {System.out.println("该图书已被借出,无法借阅!");} else {book.setBorrowed(true);System.out.println("图书借阅成功!");}return;}
    }
    • int usedSize = booklist.getUsedSize();:获取图书列表中实际存在的图书数量。
    • for (int i = 0; i < usedSize; i++):遍历图书列表中的每一本图书。
    • Book book = booklist.getBook(i);:从图书列表中获取当前索引对应的图书对象。
    • if (book.getName().equals(name)):检查当前图书的名称是否与用户输入的图书名称相同。
      • 如果相同,再检查该图书的借阅状态:
        • 如果 book.isBorrowed() 为 true,表示该图书已被借出,显示相应的提示信息。
        • 如果 book.isBorrowed() 为 false,表示该图书未被借出,将其借阅状态设置为 true,并显示借阅成功的提示信息。
      • 无论图书是否被借出,都使用 return 语句结束 work 方法
    未找到图书的处理
    System.out.println("未找到该图书!");
    return;
    • 如果遍历完整个图书列表都没有找到与用户输入的图书名称相同的图书,则显示未找到图书的提示信息,并使用 return 语句结束 work 方法。

      接下来,我们来创建一个DelOperation类,用于删除图书信息。

    • 功能:从 Booklist 中删除一本图书(按索引或书名)。
    • 核心逻辑
      • 提示用户输入要删除的图书索引或名称。
      • 找到目标图书后,将其从数组中移除(需处理数组元素的前移,避免空指针)。
      • 更新 usedSize(实际图书数量)。
    //DelOperation.java
    package operation;import book.Book;
    import book.Booklist;
    import java.util.Scanner;public class DelOperation implements IOPeration {@Overridepublic void work(Booklist booklist, Scanner scanner) {boolean needInput = true;while (true) {if (needInput) {System.out.println("请输入要删除的图书名称:");}String name = scanner.nextLine();if (name == null || name.trim().isEmpty()) {System.out.println("(注意:输入的图书名称不能为空!)");needInput = false;continue;}int usedSize = booklist.getUsedSize();for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book.getName().equals(name)) {for (int j = i; j < usedSize - 1; j++) {booklist.setBook(j, booklist.getBook(j + 1));}booklist.setUsedSize(usedSize - 1);System.out.println("图书删除成功!");return;}}System.out.println("未找到该图书!");return;}}
    }
    查找删除图书功能实现
    int usedSize = booklist.getUsedSize();
    for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book.getName().equals(name)) {for (int j = i; j < usedSize - 1; j++) {booklist.setBook(j, booklist.getBook(j + 1));}booklist.setUsedSize(usedSize - 1);System.out.println("图书删除成功!");return;}
    }
    • int usedSize = booklist.getUsedSize();:获取图书列表中实际存在的图书数量。
    • for (int i = 0; i < usedSize; i++):遍历图书列表中的每一本图书。
    • Book book = booklist.getBook(i);:从图书列表中获取当前索引对应的图书对象。
    • if (book.getName().equals(name)):检查当前图书的名称是否和用户输入的图书名称一致。
      • 若一致,通过内层的 for 循环将该图书之后的所有图书向前移动一位,覆盖掉要删除的图书。
      • booklist.setUsedSize(usedSize - 1);:将图书列表的实际数量减 1。
      • 显示删除成功的提示信息,并使用 return 语句结束 work 方法。
    未找到图书的处理
    System.out.println("未找到该图书!");
    return;
    • 若遍历完整个图书列表都未找到与用户输入的图书名称相同的图书,就显示未找到图书的提示信息,并使用 return 语句结束 work 方法。

      接下来,我们来创建一个ExitOperation,用于退出系统操作。

    • 功能:结束图书管理系统的运行。
    • 核心逻辑
      • 打印退出提示信息(如 “退出系统”)。
      • 终止程序(通常调用 System.exit(0))。
    //ExitOperation.java
    package operation;import book.Booklist;
    import java.util.Scanner;public class ExitOperation implements IOPeration {@Overridepublic void work(Booklist booklist, Scanner scanner) {System.out.println("退出系统");scanner.close();System.exit(0);}
    }

     接下来,我们来创建一个FindOperation类,用于查找图书信息。

    • 功能:在 Booklist 中查找符合条件的图书(按书名、作者、类型等)。
    • 核心逻辑
      • 提示用户输入查找条件(如书名)。
      • 遍历 Booklist 中的图书,匹配条件并打印结果。
      • 若未找到,提示 “未找到该图书”。
    //FindOperation.java
    package operation;import book.Book;
    import book.Booklist;
    import java.util.Scanner;public class FindOperation implements IOPeration {private static final String BACK_COMMAND = "back"; // 定义返回上一级菜单的指@Overridepublic void work(Booklist booklist, Scanner scanner) {boolean needInput = true;while (true) {if (needInput) {System.out.println("请输入要查找的图书名称(输入 \"" + BACK_COMMAND + "\" 返回上一级菜单):");}String name = scanner.nextLine();if (name.equalsIgnoreCase(BACK_COMMAND)) {System.out.println("已返回上一级菜单。");break;}if (name == null || name.trim().isEmpty()) {System.out.println("(注意:输入的图书名称不能为空!)");needInput = false; // 此时不需要再提示用户输入,避免重复continue;}Book foundBook = findBookByName(booklist, name);if (foundBook != null) {printBookInfo(foundBook);break;} else {System.out.println("未找到该图书!请重新输入要查找的图书名称,或输入 \"" + BACK_COMMAND + "\" 返回上一级菜单:");needInput = true; // 未找到图书,需要重新提示用户输入}}}private Book findBookByName(Booklist booklist, String name) {if (booklist == null) {return null;}int usedSize = booklist.getUsedSize();for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book == null) {continue;}if (book.getName().equals(name)) {return book;}}return null;}private void printBookInfo(Book book) {System.out.println("书名: " + book.getName());System.out.println("作者: " + book.getAuthor());System.out.println("价格: " + book.getPrice());System.out.println("类型: " + book.getType());System.out.println("是否借出: " + (book.isBorrowed()? "是" : "否"));}
    }

     findBookByName 方法 - 图书查找逻辑

    private Book findBookByName(Booklist booklist, String name) {if (booklist == null) {return null;}int usedSize = booklist.getUsedSize();for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book == null) {continue;}if (book.getName().equals(name)) {return book;}}return null;
    }

     FindOperation 类实现 work 方法,通过 booklist 获取图书列表,利用 scanner 接收用户输入的图书名称,然后在图书列表中查找该图书并输出结果。

    • 功能:在 Booklist 中查找指定名称的图书,若找到则返回该图书对象,否则返回 null
    • 分析
      • 对 booklist 进行空值检查,避免空指针异常。
      • 遍历图书列表,对每本图书进行检查,若图书名称与输入名称匹配,则返回该图书。
      • 若遍历完整个列表都未找到匹配图书,则返回 null

    接下来,我们创建一个ReturnOperation.类,用于归还图书 。

    //ReturnOperation.java
    package operation;import book.Book;
    import book.Booklist;
    import java.util.Scanner;public class ReturnOperation implements IOPeration {@Overridepublic void work(Booklist booklist, Scanner scanner) {boolean needInput = true;while (true) {if (needInput) {System.out.println("请输入要归还的图书名称:");}String name = scanner.nextLine();if (name == null || name.trim().isEmpty()) {System.out.println("(注意:输入的图书名称不能为空!)");needInput = false;continue;}int usedSize = booklist.getUsedSize();for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book == null) {continue;}if (book.getName().equals(name)) {if (book.isBorrowed()) {book.setBorrowed(false);System.out.println("图书归还成功!");} else {System.out.println("该图书未被借出,无需归还!");}return;}}System.out.println("未找到该图书!");return;}}
    }
     图书查找与归还
    int usedSize = booklist.getUsedSize();
    for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);if (book == null) {continue;}if (book.getName().equals(name)) {if (book.isBorrowed()) {book.setBorrowed(false);System.out.println("图书归还成功!");} else {System.out.println("该图书未被借出,无需归还!");}return;}
    }
    • 功能:在图书列表中查找用户输入的图书,并根据图书的借阅状态进行相应处理。
    • 分析
      • 首先获取图书列表的实际使用大小 usedSize,然后使用 for 循环遍历图书列表。
      • 若当前图书对象为 null,使用 continue 语句跳过本次循环,继续检查下一本图书。
      • 若找到与用户输入名称匹配的图书,检查其借阅状态:
        • 若图书已被借出(book.isBorrowed() 为 true),将图书的借阅状态设置为 false,表示归还成功,并输出相应提示信息,然后使用 return 语句结束方法。
        • 若图书未被借出,输出 “该图书未被借出,无需归还!” 的提示信息,然后结束方法。

    接下来,我们创建一个ShowOperation类展示所有图书。

    • 功能:遍历 Booklist 并打印所有图书的详细信息。
    • 核心逻辑
      • 遍历 Booklist 的 Books 数组,根据 usedSize 确定有效范围。
      • 调用每本图书的 toString() 方法,输出其名称、作者、价格、类型、借阅状态等。
    //ShowOperaetion.java
    package operation;import book.Book;
    import book.Booklist;import java.util.Scanner;public class ShowOperation implements IOPeration {@Overridepublic void work(Booklist booklist,Scanner scanner) {int usedSize = booklist.getUsedSize();if (usedSize == 0) {System.out.println("图书列表为空!");} else {for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);System.out.println("书名: " + book.getName());System.out.println("作者: " + book.getAuthor());System.out.println("价格: " + book.getPrice());System.out.println("类型: " + book.getType());System.out.println("是否借出: " + (book.isBorrowed() ? "是" : "否"));System.out.println("-------------------");}}}
    }

     work方法实现图书信息输出

    @Override
    public void work(Booklist booklist, Scanner scanner) {int usedSize = booklist.getUsedSize();if (usedSize == 0) {System.out.println("图书列表为空!");} else {for (int i = 0; i < usedSize; i++) {Book book = booklist.getBook(i);System.out.println("书名: " + book.getName());System.out.println("作者: " + book.getAuthor());System.out.println("价格: " + book.getPrice());System.out.println("类型: " + book.getType());System.out.println("是否借出: " + (book.isBorrowed() ? "是" : "否"));System.out.println("-------------------");}}
    }
    • @Override:注解表明该方法是重写 IOPeration 接口中的 work 方法。
    • int usedSize = booklist.getUsedSize();:获取图书列表中实际存在的图书数量。
    • if (usedSize == 0):检查图书列表是否为空,如果为空则输出提示信息。
    • for (int i = 0; i < usedSize; i++):如果图书列表不为空,使用 for 循环遍历图书列表。
    • Book book = booklist.getBook(i);:从图书列表中获取当前索引对应的图书对象。
    • 接下来的一系列 System.out.println 语句用于输出每本图书的详细信息,包括书名、作者、价格、类型和借阅状态,并使用分隔线 "-------------------" 分隔不同图书的信息。

    3. user模块实现

    在user模块中,我们需要实现管理员和普通用户两个模块。

    首先,我们来创建一个user模块,用来管理用户;

    package user;import book.Booklist;
    import operation.IOPeration;
    import java.util.Scanner;public abstract class User {protected String name;public IOPeration[] IOPerations;public User(String name) {this.name = name;}public abstract int menu(Scanner scanner);public void doOperation(int choice, Booklist booklist, Scanner scanner) {IOPerations[choice].work(booklist, scanner);}
    }

    public abstract class User中:

    • abstract:表示这是一个抽象类,不能直接创建实例(需通过子类继承并实现抽象方法后使用)。
    • 作用:作为所有用户类型(管理员、普通用户)的父类,定义公共属性和行为规范。
    public User(String name) {this.name = name;
    }

    这段代码中,我们使用了抽象方法menu,用来显示不同用户的菜单(管理员菜单 / 普通用户菜单),并通过 Scanner 获取用户输入的操作选项(如 1 表示 “查找图书”,0 表示 “退出”)。

    我们使用 doOperation方法根据用户选择的菜单选项,执行对应的操作。

    public void doOperation(int choice, Booklist booklist, Scanner scanner) {IOPerations[choice].work(booklist, scanner);
    }
    • choice:用户输入的选项(如 1 对应 IOPerations[1])。
    • booklist:图书列表对象,用于操作图书数据(如添加、删除、借阅)。
    • scanner:扫描器对象,用于在操作中获取用户输入(如新增图书时输入书名)。
    • 通过 IOPerations[choice] 找到对应的操作类(如 FindOperation),调用其 work 方法(定义在 IOPeration 接口中),实现具体功能(如查找图书)。
    • 通过 IOPerations 数组差异化配置不同用户的可执行操作,实现了管理员与普通用户的功能分离。

      下面让我们来看管理员模块,AdminUser.java

    package user;import operation.*;
    import java.util.Scanner;public class AdminUser extends User {public AdminUser(String name) {super(name);this.IOPerations = new IOPeration[]{new ExitOperation(),new FindOperation(),new AddOperation(),new DelOperation(),new ShowOperation()};}public int menu(Scanner scanner) {System.out.println("*************************");System.out.println("Hello" + this.name + "欢迎来到图书管理员菜单");System.out.println("1.查找图书");System.out.println("2.新增图书");System.out.println("3.删除图书");System.out.println("4.显示图书");System.out.println("0.退出系统");System.out.println("*************************");System.out.println("请输入你的操作:");return scanner.nextInt();}
    }

    AdminUser.java继承了他的父类user,并且必须实现 User 类中定义的抽象方法,,实现了管理员用户的特定功能。

    public AdminUser(String name) {super(name);this.IOPerations = new IOPeration[]{new ExitOperation(),new FindOperation(),new AddOperation(),new DelOperation(),new ShowOperation()};
    }
    • super(name);:调用父类 User 的构造方法,将管理员的姓名传递给父类进行初始化。
    • this.IOPerations = ...:初始化 IOPerations 数组,该数组存储了管理员用户可以执行的操作。数组中的每个元素都是 IOPeration 接口的实现类的实例,分别对应退出系统、查找图书、新增图书、删除图书和显示图书这五个操作。
    • 简而言之就是管理员系统通过IOPeration 接口来删除增加查找图书。

    下面让我们来看普通用户模块,NormalUser.java

    package user;import operation.*;
    import java.util.Scanner;public class NormalUser extends User {public NormalUser(String name) {super(name);this.IOPerations = new IOPeration[]{new ExitOperation(),new FindOperation(),new BorrowedOperation(),new ReturnOperation()};}public int menu(Scanner scanner) {System.out.println("*************************");System.out.println("Hello" + this.name + "欢迎来到普通用户菜单");System.out.println("1.查找图书");System.out.println("2.借阅图书");System.out.println("3.归还图书");System.out.println("0.退出系统");System.out.println("*************************");System.out.println("请输入你的操作:");return scanner.nextInt();}
    }

    NormalUser 类代表了图书管理系统中的普通用户,通过继承 User 类,它继承了用户的基本属性和行为。在构造方法中,初始化了普通用户可以执行的操作列表;在 menu 方法中,显示了普通用户的菜单并获取用户的操作选择。


    四、主菜单 

    import book.Booklist;
    import user.AdminUser;
    import user.NormalUser;
    import user.User;import java.util.Scanner;public class Main {public static User login(Scanner scanner) {System.out.println("请输入你的姓名:");String name = scanner.nextLine();int choice;while (true) {System.out.println("请输入你的身份:1. 管理员 0. 普通用户");try {choice = scanner.nextInt();scanner.nextLine(); // 消耗掉换行符if (choice == 0 || choice == 1) {break;} else {System.out.println("输入无效,请输入 0 或 1。");}} catch (Exception e) {System.out.println("输入无效,请输入一个整数。");scanner.nextLine(); // 清除无效输入System.out.println("异常信息: " + e.getMessage());e.printStackTrace(); // 打印异常的堆栈跟踪信息}}if (choice == 1) {return new AdminUser(name);} else {return new NormalUser(name);}}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);Booklist booklist = new Booklist();User user = login(scanner);while (true) {int choice = user.menu(scanner);user.doOperation(choice, booklist, scanner);}}
    }

    菜单部分就比较简单,login方法

    • 用户姓名输入:提示用户输入姓名,并且读取用户输入的姓名。
    • 用户身份选择:提示用户输入身份(1 代表管理员,0 代表普通用户),同时对用户输入进行有效性验证。若输入无效,会提示用户重新输入。
    • 用户对象创建:依据用户输入的身份,创建对应的 AdminUser 或者 NormalUser 对象。
    • Exception:这是 Java 中所有异常类的父类。Java 里的异常类构建了一个类层次结构,Exception 处于这个层次结构的核心位置,许多具体的异常类都继承自它,像 IOExceptionNullPointerExceptionInputMismatchException 等。
    • e:这是一个引用变量,其类型为 Exception。在异常捕获时,它会指向实际抛出的异常对象。借助这个引用变量,你能够访问异常对象的属性和方法,进而获取异常的相关信息,例如异常的类型、错误信息等。
    • 若用户输入的不是有效的整数,scanner.nextInt() 就会抛出 InputMismatchException 异常。
    • try 块里尝试读取用户输入的整数。
    • 若用户输入的不是有效的整数,scanner.nextInt() 就会抛出 InputMismatchException 异常。
    • catch (Exception e) 捕获这个异常,将异常对象赋值给 e
    • 接着可以通过 e.getMessage() 获取异常的详细信息,使用 e.printStackTrace() 打印异常的堆栈跟踪信息,这有助于调试程序。

    main方法中,我们创建 Scanner 对象用于读取用户输入,创建 Booklist 对象来管理图书列表,调用 login 方法完成用户登录。

    项目地址

    booktest · 王磊鑫/JAVA - 码云 - 开源中国

    相关文章:

  • B2B2C多用户商城平台 的两种创新玩法
  • 华熙生物亮相消博会,这次又带来了什么样的变化?
  • springboot项目添加定时任务,用sftp推送zip包到目标服务器
  • 车载信息安全 --- 密钥管理
  • Anaconda笔记
  • C语言-习题整理(1)
  • 第 2 篇:快速上手 Framer Motion(实操入门)
  • 烽火ai场控接入deepseek自动回复话术软件
  • 【Python】列表的创建:[[] for _ in range(2)] 与 [[]] * 2有什么区别?
  • STM32F407实现内部FLASH的读写功能
  • 【MySQL】MySQL数据库 —— 简单认识
  • 第3篇:深入 Framer Motion Variants:掌握组件动画编排的艺术
  • django项目之添加资产信息功能
  • YOLOv3模型架构与原理详解
  • Python 冷门魔术方法
  • Redis 高可用集群搭建与优化实践
  • 波束形成(BF)从算法仿真到工程源码实现-第十节-非线性波束形成
  • vue中使用swiper坑记录
  • 二、The Power of LLM Function Calling
  • 京东商品详情API接口调用讲解(实战案例)
  • 一女子称醉酒后疑似被性侵,长沙警方通报:嫌犯邱某某已被刑拘
  • 嵩山少林风景区女游客进男厕:不能止步于批评
  • 东莞一初中生跑操时倒地身亡,家属质疑校方施救不力
  • 九部门:将符合条件的家政从业人员纳入公租房等保障范围
  • 硅基世界的“缘分”——系统与人工智能携手进化
  • 农业农村部原党组书记、部长唐仁健被提起公诉