首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >图书系统(新)

图书系统(新)

作者头像
景画
发布2025-12-19 13:51:58
发布2025-12-19 13:51:58
520
举报

一. 模式

(一)单例模式

一个类有且只有一个实例对象,所以这就需要我们不能在别的类调用单例类的构造方法,于是可以将构造方法私有化,那么该对象只能通过静态方法来获取

(1)饿汉式单例模式
1. 定义

每次程序运行时都实例化一个对象,不管是否用到,先确保该对象是存在的,即饿汉式单例模式

2. 代码
代码语言:javascript
复制
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. 代码
代码语言:javascript
复制
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多个用户,创建对象与使用对象方法分离,实现低耦合

(三)代理模式

代码语言:javascript
复制
代理模式就是通过代理对象来控制对实际对象的访问,起到一个跳转作用

二. 图书系统框架

(一)user

用户User有管理员Root与普通用户NormalUser,所以抽取Root与NormalUser的共同属性与方法,将User定义为抽象类 定义抽象类属性:

  1. String name;(名字)
  2. int ID;(用户id)
  3. String role;(身份)
  4. display()(菜单)
  5. Scanner scanner(输入操作)
(1)Root
代码语言:javascript
复制
root用户对应着管理员的菜单,且role可以写死为**管理员**
代码语言:javascript
复制
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, "管理员");
    }

    @Override
    public 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
代码语言:javascript
复制
NormalUser对应着普通用户的菜单,role可以写死为**普通用户**
代码语言:javascript
复制
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, "普通用户");
    }

    @Override
    public 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,再设置两个类,RootFactoryNormalFactory实现该接口,RootFactory来实例化Root对象,NormalFactory实例化NormalUser对象

1. IUserFactory
代码语言:javascript
复制
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
代码语言:javascript
复制
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{
    @Override
    public User createUser(String name, int ID) {
        return new Root(name,ID);
    }
}
3. NormalFactory
代码语言:javascript
复制
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{
    @Override
    public User createUser(String name, int ID) {
        return new NormalUser(name,ID);
    }
}
(5)引入代理模式

将管理员与普通用户的所有方法放入代理类当中,从而实现代理,代理时,根据用户可以根据用户选择身份的不同来接收不同的对象,从而打印选择不同的菜单

代码语言:javascript
复制
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

图书系统中必须要有的就是书 书的属性:

  1. 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; // 上架时间
  2. 其中借阅状态,借阅次数默认就是想要的值,且书的ID我们会设置其自增,所以这三个属性都不用初始化,构造方法去掉这三个属性,我们也不希望普通用户来修改书的属性,所以都私有化,同时提供get与set方法,来供root用户修改提供方法
代码语言:javascript
复制
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; //书id
    private 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;
    }

    @Override
    public String toString() {
        return "Book{" +
                "bookId=" + bookId +
                ", 书名='" + title + '\'' +
                ", 作者='" + author + '\'' +
                ", 类别='" + category + '\'' +
                ", 出版年份=" + publishYear +
                ", 是否借阅=" + isBorrowed +
                ", 借阅次数=" + borrowCount +
                ", 上架时间=" + shelfDate +
                '}';
    }
}
(2)AnalyzingBook

希望将每本书都可以永久保存,这需要用到文件,所以需要专门定义一个类来实现读取书写书的功能,同时与图书馆library和图书book交互

代码语言:javascript
复制
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) {
                // 除了最后一行,将每行都拼接杀那个一个换行符\n
                stringBuilder.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)

代码语言:javascript
复制
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时一个性质

代码语言:javascript
复制
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交互

代码语言:javascript
复制
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交互,所以最终落实到普通用户类

代码语言:javascript
复制
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();
    }

    @Override
    public 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中

起到跳转作用

代码语言:javascript
复制
    public void addBook() {
        checkRealUserWhetherAdminUser("你不是root用户!!!");
        ((Root)proxyUser).addBook();
    }
2. Root中

准备书的信息

代码语言:javascript
复制
 //上架图书
    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中

注意一定要写入文件当中

代码语言:javascript
复制
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中

起到跳转作用

代码语言:javascript
复制
   //更新书籍操作
    public void updateBook() {
        checkRealUserWhetherAdminUser("你不是root用户!!!");
        ((Root)proxyUser).updateBook();
    }
2. Root中

准备书的信息

代码语言:javascript
复制
    //图书修改 ⽀持修改书名 作者 类别
    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中

注意一定要写入文件当中

代码语言:javascript
复制
    public void updateBook(Book book) {
        //先找到该书是哪个下标
        int index = searchByIdReturnIndex(book.getBookId());
        books[index] = book;
        System.out.println("图书:"  + book.getTitle() +" 更新成功!");
        //⼀定要进⾏存储
        writeBook();
    }
(3)removeBook

删除图书

1. proxyUser中

起到跳转作用

代码语言:javascript
复制
    public void removeBook() {
        checkRealUserWhetherAdminUser("你不是root用户!!!");
        ((Root)proxyUser).removeBook();
    }
2. Root中

通过id查找是否存在这本书

代码语言:javascript
复制
    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中

在图书馆删除书的信息,然后写入文件当中

代码语言:javascript
复制
    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中

起到跳转作用,又因为借阅图书和普通用户有关

代码语言:javascript
复制
   public void borrowCount( ) {
        checkRealUserWhetherAdminUser("你不是root用户!!!");
        ((Root)proxyUser).borrowCount();
    }
2. Root中

因为借阅图书和普通用户及图书馆有关,所以只能跳转到图书馆

代码语言:javascript
复制
   public void borrowCount() {
        library.borrowCount();
    }
3. Library中

先加载图书,然后在图书馆找书的借阅信息,最后打印出来

代码语言:javascript
复制
    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中

起到跳转作用

代码语言:javascript
复制
    public void generateBook() {
        checkRealUserWhetherAdminUser("你不是root用户!!!");
        ((Root)proxyUser).generateBook();
    }
2. Root中

先让用户输入k的值,k值也应该做限定

代码语言:javascript
复制
    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接口

代码语言:javascript
复制
 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中
代码语言:javascript
复制
    @Override
    public int compareTo(Book o) {
        return o.borrowCount - this.borrowCount;
    }
(6)checkInventoryStatus

查看库存状态

1. ProxyUser中

跳转作用

代码语言:javascript
复制
    public void checkInventoryStatus() {
        checkRealUserWhetherAdminUser("你不是root用户!!!");
        ((Root)proxyUser).checkInventoryStatus();
    }
2. Root中

跳转作用

3. Library中

打印每本书的借阅状态和名字

代码语言:javascript
复制
   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中

跳转作用

代码语言:javascript
复制
 public void checkAndRemoveOldBooks() {
        checkRealUserWhetherAdminUser("你不是root用户!!!");
        ((Root)proxyUser).checkAndRemoveOldBooks();
    }
2. Root中

跳转作用

代码语言:javascript
复制
    public void checkAndRemoveOldBooks() {
        library.checkAndRemoveOldBooks();
    }
3. Library中

  1. 加载书籍信息
  2. 先获取当前时间戳 long currentTimestamp = System.currentTimeMillis();
  3. 将当前时间转化为LocalDate类型 LocalDate currentDate = Instant.ofEpochMilli(currentTimestamp).atZone(ZoneId.systemDefault()).toLocalDate();
  4. 遍历books数组,获取每本书的LocalDate上架时间 LocalDate specifiedDate = book.getShelfDate();
  5. 按年份比较LocalDate上架时间 long yearsBetween = ChronoUnit.YEARS.between(specifiedDate, currentDate);
  6. 查看相差年份大于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); } }
  7. 判断是否有书籍大于1年,没有的话给出提示 if (flag) { return; } System.out.println(“没有上架超过⼀年的图书!”);
代码语言:javascript
复制
 public void checkAndRemoveOldBooks() {
        loadAllBook();
        // 获取当前时间戳
        long currentTimestamp = System.currentTimeMillis();
        // 将当前时间戳转换为 LocalDate
        LocalDate 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,跳转作用

代码语言:javascript
复制
    public void borrowBook() {
        checkRealUserWhetherNormalUser("请切换普通用户");
        ((NormalUser)proxyUser).borrowBook();
    }
2. NormalUser

  1. 先展示书架的书
  2. 没有书则不能借阅
  3. 根据展示来输入要借阅的书的id
  4. 加载借阅书籍的信息
  5. 根据id查找该本书,如果没有找到,提示用户,并且结束进程
  6. 如果有该本书,那么先查找该本书的借阅信息,查看该本书是否被借阅过
  7. 如果被借阅过那么要判断是被自己借阅过还是别人借阅过,打印出借阅人的id与名字
  8. 没有被借阅过,那么开始借阅,跳转到图书馆开始借阅,并且将你的id与名字,以及书的id封装到BorrowedUidAndBookId中
  9. 写入到BorrowBook中
  10. 最后提示借阅成功
代码语言:javascript
复制
    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中

  1. 加载书籍信息
  2. 根据传入的bookId来找到对应书籍
  3. 将该书籍的isBorrowed改为true
  4. 写入文件
代码语言:javascript
复制
    public void borrowBook(int bookId) {
        loadAllBook();
        Book book = searchById(bookId);
        book.setBorrowed(true);
        book.incrementBorrowed();
        writeBook();
    }
(9)returnBook

归还书籍

1. proxyUser

跳转

代码语言:javascript
复制
  public void returnBook() {
        checkRealUserWhetherNormalUser("请切换普通用户");
        ((NormalUser)proxyUser).returnBook();
    }
2. NormalUser

  1. 先加载借阅信息
  2. 如果借阅次数为0,那么不能归还,结束进程
  3. 打印当前所有书籍的借阅信息
  4. 输入要归还的书籍id
  5. 查找该书,为null则不用归还
  6. 有这本书,就要查看借阅表中有没有该书
  7. 遍历借阅表中有这本书,说明该属被借阅了,那么比较借阅id与本人id,相同则可以归还,不相同那么不能归还,说明是别人借的,要打印出借阅人的id与名字,都结束进程
  8. 归还的时候采用最后一个覆盖该位置信息的方法,将借阅数组最后一个置为null,借阅数量-1,并写入借阅表
  9. 遍历借阅表结束,都没有结束程序,那么说明这本书,没有被借出去
代码语言:javascript
复制
    public void returnBook() {
        // 加载借阅书籍
        loadBorrowedBook();
        // 判断借阅次数
        if (borrowedCount == 0) {
            System.out.println("当前没有任何借阅书籍,你不能归还!!!");
            return;
        }
        // 打印借阅情况
        System.out.println("当前所有的借阅书籍情况如下:");
        library.disBorrowedStatus();
        // 输入归还书籍id
        System.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,并写入文件

代码语言:javascript
复制
    public void returnBook(int bookId) {
        loadAllBook();
        Book book = searchById(bookId);
        book.setBorrowed(false);
        writeBook();
    }
(10)viewBorrowHistory

查看个人正在借阅所有书的情况

1. proxyUser

代理,跳转

代码语言:javascript
复制
    public void viewBorrowHistory() {
        checkRealUserWhetherNormalUser("请切换普通用户");
        ((NormalUser)proxyUser).viewBorrowBooks();
    }
2. NormalUser

  1. 加载借阅情况
  2. 如果borrowedCount为0,那么当前没有借阅任何书籍
  3. 不为0,那么遍历借阅表,打印与自己id相同的借阅书籍,
  4. 设置一个布尔变量,打印则改变值,来最后判断是否真的借阅了书籍
代码语言:javascript
复制
    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

查找图书,我们设置根据名字来查找,又因为书名可能重复,所以我们遍历数组找

代码语言:javascript
复制
    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

退出系统的方法

代码语言:javascript
复制
  public void exit() {
        System.out.println("系统已退出。。。");
        System.exit(0);
    }
(13)displayBooks

打印当前所有图书,bookCount为0,则说明没有书籍,否则就打印

代码语言:javascript
复制
   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

切换角色的方法,切换角色无非就是重新跳转到生成挑选角色的方法,我们可以把生成角色的方法封装起来,每次调用可以回到最初状态

代码语言:javascript
复制
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;
    }
}

四. 总结

该博客花了小编多天时间,拓展了一两个小功能,希望可以博得你的一个点赞

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 模式
    • (一)单例模式
      • (1)饿汉式单例模式
      • (2)懒汉式单例模式
    • (二)工厂模式
    • (三)代理模式
  • 二. 图书系统框架
    • (一)user
      • (1)Root
      • (2)NormalUser
      • (3)相同方法
      • (4)引入工厂模式
      • (5)引入代理模式
    • (二)book
      • (1)Book
      • (2)AnalyzingBook
      • (3)Library
      • (4)BorrowedUidAndBookId
      • (5)AnalyzingBorrowedBook
      • (6)再谈NormalUser
  • 三. 方法实现
    • (一)管理员方法
      • (1)addBook
      • (2)updateBook
      • (3)removeBook
      • (4)borrowCount
      • (5)generateBook
      • (6)checkInventoryStatus
      • (7)checkAndRemoveOldBooks
    • (二)普通用户方法
      • (8)borrowBook
      • (9)returnBook
      • (10)viewBorrowHistory
    • (三)共同方法
      • (11)searchBook
      • (12)exit
      • (13)displayBooks
      • (14)start
  • 四. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档