Java项目 简易图书管理系统

面向对象是Java中最重要的思想,本图书管理系统就是以面向对象为中心,逐层拆解业务。

首先抽象出对象,一想到图书管理系统,我们就会想到 书和 能操作书的人 。

但只有书还不够 还需要 一个书架 来进行管理

那么 总结 下来

我们需要创建 书类(Book) 、管理书的书架类(BookList)、用户类(User)

每个事物都有自己的属性,那么我们就需要考虑 这三个类 都有什么成员属性和成员方法


自定义类

  1. Book类

成员属性:书名(name),作者名(author),价格(price),类型(type),是否被借出的状态(state)

构造方法:初始化Book

成员方法:因为我们不希望外界干扰这些关键信息,因此都需要用 private 修饰。因此每个成员属性都要有 get 和 set 方法

  1. BookList类

书架上需要放很多的书,那么书籍的底层数据结构用数组最合适不过了

成员属性:书架(Book[] books),书架的长度(usedSize)

构造方法:初始化Books (默认有三本书)

成员方法:因为我们不希望外界干扰这些关键信息,因此都需要用 private 修饰。因此每个成员属性都要有 get 和 set 方法

  1. User类

对于用户来说 要 分为 管理权限高的 管理员和 权限比较低的 普通用户。

管理员的权限功能: 显示图书、增加图书、删除图书、查询图书、退出系统

普通用户的权限功能:查询图书、借阅图书、归还图书、退出系统

那么我们要根据用户的不同来分别呈现对应的菜单功能,因此我们需要借助多态的思想。

但实现多态的前提,需要继承,因此我们需要有User这个大类,并让普通用户(NomralUser)和 管理员(AdminUser) 继承User。

成员属性:姓名(name)

构造方法:初始化name

成员方法:菜单选项(menu)

因为用户不同,所以对应的菜单打印也不同,因此 NomralUser 和 AdminUser类 也都需要重写父类的 menu方法。那么 menu 方法 应该由 abstract 修饰 并且 User类也不能用来具体表示某个对象只是泛称因此也要用 abstract 修饰。


自定义接口

因为 NomralUser 和 AdminUser 对于的菜单操作方法不同,我们可以创建接口数组,利用接口数组组织这些操作,需要用到哪个直接按照用户输入的数字,调用出对应数组下标的操作方法。

但接口并不能直接创建和实现, 因此 我们需要对每个操作都创建对应的类 然后 将这些类实现接口。

"管理员" 需要的操作:显示图书信息、增加图书信息、删除图书信息、查询图书信息、退出系统
"用户" 需要的操作:查询图书信息、借阅图书、归还图书、退出系统

这些操作,分别定义成 :
"Add" 增加
"Delete" 删除
"Show" 显示
"Find" 查找
"Borrow" 借阅
"Return" 归还
"Exit" 退出

让这些 都 实现Operation 这个接口,在 Operation 接口中 定义一个抽象方法: work() ,这样就只需要在这些 中重写 **work()**方法即可


代码书写

我们根据上面的这些 分析,进行编写代码

book 包

创建一个 book包 里面有 Book类 和 BookList类

Book类

java 复制代码
package book;

public class Book {
    private String name;
    private String author;
    private int price;
    private String type;
    private boolean state;

    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 int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public boolean isState() {
        return state;
    }

    public void setState(boolean state) {
        this.state = state;
    }

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

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                (state == true ? "已借出": "未借出") +
//                ", state=" + state +
                '}';
    }


}

可以看到构方法中没有 state 这个参数,是因为 boolean 类型的变量即使不初始化,系统也会赋给一个默认值,默认为 "false"

BookList类

java 复制代码
package book;

public class BookList {

    private Book[] books = new Book[10];
    private int usedSize;

    public BookList(Book[] books, int usedSize) {
        books[0] = new Book("铁道概论","张三",10,"教科书");
        books[1] = new Book("电路分析基础","李四",15,"教科书");
        books[0] = new Book("区间闭塞设备维修","王五",20,"教科书");
        this.usedSize = 3;
    }

    public int getUsedSize() {
        return usedSize;
    }

    public void setUsedSize(int usedSize) {
        this.usedSize = usedSize;
    }
}
}

创建书架时,默认书架上有三本书


user包

创建一个user包,里面分别有 User 父类,继承User的子类 NomralUser 和 AdminUser类

User类

java 复制代码
package user;

//因为User不能表达某个具体的对象
//并且有抽象方法,因此为抽象类

import book.BookList;

public abstract class User {
    protected String name;
    protected IOPeration[] ioPerations;//接口数组 分别放置不同的操作

    public User(String name) {
        this.name = name;
    }

    //抽象方法的原因,根据子类各自的情况,呈现不同的菜单详情,因此父类 menu 方法 不用有具体实现
    public abstract int menu();

}

AdminUser 子类

java 复制代码
package user;

public class AdminUser extends User{

    public AdminUser(String name) {
        super(name);
    }

    @Override
    public void menu() {
        System.out.println("------------管理员菜单------------");
        System.out.println("1.查找图书");
        System.out.println("2.新增图书");
        System.out.println("3.删除图书");
        System.out.println("4.显示图书");
        System.out.println("0.退出系统");
        System.out.println("------------------------------------------------");
    }
}

NomralUser 子类

java 复制代码
public class NomralUser extends User{


    public NomralUser(String name) {
        super(name);
    }

    @Override
    public void menu() {
        System.out.println("------------普通用户菜单------------");
        System.out.println("1.查找图书");
        System.out.println("2.借阅图书");
        System.out.println("3.归还图书");
        System.out.println("0.退出系统");
        System.out.println("------------------------------------------------");
    }

}

operation包

存放接口 IOPeration,和其他操作类

添加图书:AddOperation

借阅图书:BorrowedOpreation

删除图书:DelOperation

退出系统:ExitOpreation

寻找图书:FindOperation

归还图书:ReturnOpreation

显示图书:ShowOperation

接口 IOPeration

java 复制代码
package operation;

import book.BookList;


public interface IOPeration {
    void work(BookList booklist);
}

AddOperation类

java 复制代码
public class AddOperation implements IOperation{

    @Override
    public void work() {

    }
}

BorrowedOpreation类

java 复制代码
public class BorrowedOpreation implements IOperation{
    @Override
    public void work() {

    }
}

DelOperation类

java 复制代码
public class DelOperation implements IOperation{
    @Override
    public void work() {

    }
}

ExitOpreation类

java 复制代码
public class ExitOpreation implements IOperation{
    @Override
    public void work() {

    }
}

FindOperation类

java 复制代码
public class FindOperation implements IOperation{
    @Override
    public void work() {

    }
}

ReturnOpreation类

java 复制代码
public class ReturnOpreation implements IOperation {
    @Override
    public void work() {

    }
}

ShowOperation类

java 复制代码
public class ShowOperation implements IOperation{
    @Override
    public void work() {

    }
}

基本准备工作准备好了之后,我们就要代入操作者的视角,进行操作内容的搭建

  1. 登录系统

  2. 选择身份

  3. 选择想要进行的操作

程序入口

我们可以在src包下创建一个Main类,作为程序的入口

Main类

java 复制代码
public static User login(){
        System.out.println("请输入你的姓名");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();

        System.out.println("请选择你的身份 1-> 管理员 2-> 普通用户");

        int choice = scanner.nextInt();
        if(choice == 1){
            AdminUser adminUser = new AdminUser(name);
            return adminUser;
        } else{
            NomralUser nomralUser = new NomralUser(name);
            return nomralUser;
        }

    }


    public static void main(String[] args) {

        //第一步 创建书架
        BookList bookList = new BookList();
        //第二步 根据输入,获取用户权限信息
        //向上转型
        User user = login();

我们根据输入的数字进入new对应身份的对象,然后用 User父类引用对象 接收,这里就是向上转型,并为下面根据 不同的身份打印不同的菜单(多态)提供了前提条件

java 复制代码
public static User login(){
        System.out.println("请输入你的姓名");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();

        System.out.println("请选择你的身份 1-> 管理员 2-> 普通用户");

        int choice = scanner.nextInt();
        if(choice == 1){
            AdminUser adminUser = new AdminUser(name);
            return adminUser;
        } else{
            NomralUser nomralUser = new NomralUser(name);
            return nomralUser;
        }

    }


    public static void main(String[] args) {

        //第一步 创建书架
        BookList bookList = new BookList();
        //第二步 根据输入,获取用户权限信息
        //向上转型
        User user = login();
        //第三步 利用多态思想 打印对应菜单 并获取 选项
        int choice = user.menu();

    }

接下来我们只剩下对 操作的处理

因为 管理员 和 普通用户 既有相同操作又有不同的操作,那么我们就需要用接口数组。在数组中存放相应的操作,当用户输入操作数字,我们只需根据输入 将数组对应下标的方法调用即可。

所以我们在 User 父类中:

补充一个成员属性:IOperations 数组,只声明即可,在子类中利用构造方法帮助父类进行初始化这个数组

补充一个成员方法: doIoperation(),利用下标访问对应的类中的 work 方法

补充 User 父类

java 复制代码
public abstract class User {
    protected String name;

    //新增
    protected IOperation[] ioPerations;

    public User(String name) {
        this.name = name;
    }

    public abstract int menu();

    //新增
    public void doIoperation(int choice, BookList booklist) {
        this.ioPerations[choice].work(booklist);
    }

}

补充子类的构造方法

java 复制代码
public AdminUser(String name) {
        super(name);
        this.ioPerations = new IOPeration[]{
                new ExitOperation(),
                new FindOperation(),
                new AddOperation(),
                new DelOperation(),
                new ShowOpreation()

        };
    }
java 复制代码
public NormalUser(String name) {
        super(name);
        this.ioPerations = new IOPeration[]{
                new ExitOperation(),
                new FindOperation(),
                new BorrowedOperation(),
                new ReturnOperation()
        };
    }

根据构造方法,就可以初始化数组了

最后补全方法调用语句 user.doIoperation();

java 复制代码
public static void main(String[] args) {

        //第一步 创建书架
        BookList bookList = new BookList();
        //第二步 根据输入,获取用户权限信息
        //向上转型
        User user = login();
        //第三步 利用多态思想 打印对应菜单 并获取 选项
        int choice = user.menu();

        //调用方法 体现了动态绑定

        user.doIoperation(choice,bookList);

    }

最后我们只剩具体操作的核心逻辑了

补全操作

AddOperation类

java 复制代码
public class AddOperation implements IOPeration{
    public void work(BookList bookList){
        System.out.println("新增图书");

        if(bookList.isFull()){
            System.out.println("书架满了 不能新增了");
            return;
        }

        System.out.println("请输入你要新增的图书的书名");
        Scanner scanner = new Scanner(System.in);
        String bookName = scanner.nextLine();

        System.out.println("请输入你要新增的图书的作者");
        String author = scanner.nextLine();

        System.out.println("请输入你要新增的图书的类型");
        String type = scanner.nextLine();
        
        System.out.println("请输入你要新增的图书的价格");
        int price = scanner.nextInt();

        Book book = new Book(bookName,author,price,type);
        //在数组的末尾加入数据

        int currentSize = bookList.getUsedSize();
        bookList.setBook(currentSize,book);
        bookList.setUsedSize(currentSize+1);
        System.out.println("新增图书成功!");


    }
}

BorrowedOperation类

java 复制代码
public class BorrowedOperation implements IOPeration{
    public void work(BookList bookList){
        System.out.println("借阅图书");

        System.out.println("请输入你想要借阅的图书");
        Scanner scanner = new Scanner(System.in);
        String bookName = scanner.nextLine();
        int currentSize = bookList.getUsedSize();

        for (int i = 0; i < currentSize; i++) {

            Book book = bookList.getBook(i);
            if(book.getName().equals(bookName)){
                book.setState(true);
                System.out.println("借阅成功");
                return;
            }
        }

        System.out.println("借阅失败");
    }
}

DelOperation类

java 复制代码
public class DelOperation implements IOPeration{
    public void work(BookList bookList){
        System.out.println("删除图书");

        System.out.println("请输入你要删除的图书的书名: ");
        Scanner scanner = new Scanner(System.in);
        String bookName = scanner.nextLine();

        int currentSize = bookList.getUsedSize();
        //初始化下标
        int pos = -1;
        int i = 0;
        for (; i < currentSize; i++) {

            Book book = bookList.getBook(i);
            if (book.getName().equals(bookName)){
                //代码执行到这里时,已经说明 找到了这本书
                //记录下标
                pos = i;
                break;
            }


        }
        if (i >= currentSize){
            System.out.println("没有你要删除的图书");
            return;
        }

        //开始删除
        for(int j = pos; j < currentSize - 1;j++){
            bookList.setBook(j,bookList.getBook(j+1));
//           Book book = bookList.getBook(j+1);
//           bookList.setBook(j,book);
        }

        //删除之后,修改usedSize
        bookList.setUsedSize(currentSize-1);
        bookList.setBook(currentSize-1 ,null);

    }
}

ExitOperation类

java 复制代码
public class ExitOperation implements IOPeration{
    public void work(BookList bookList){
        System.out.println("退出系统");

        int currentSize = bookList.getUsedSize();
        for (int i = 0; i < currentSize; i++) {
            bookList.setBook(i,null);
        }


        // 0 代表正常退出
        System.exit(0);
    }
}

FindOperation类

java 复制代码
public class FindOperation implements IOPeration{
    public void work(BookList bookList){
        System.out.println("寻找图书");
        System.out.println("请输入你要查找的图书名:");
        Scanner scanner = new Scanner(System.in);
        String bookName = scanner.nextLine();

        int currentSize = bookList.getUsedSize();

        for(int i = 0; i < currentSize; i++){
            Book book = bookList.getBook(i);
            if(book.getName().equals(bookName)){
                System.out.println("找到了这本书:");
                System.out.println(book);
                //因为重写了Book 的 toString 方法
                return;
            }
        }

        System.out.println("没有你要找的书");


    }
}

ReturnOperation类

java 复制代码
public class ReturnOperation implements IOPeration{
    public void work(BookList bookList){
        System.out.println("归还图书");

        System.out.println("请输入你想要归还的图书");
        Scanner scanner = new Scanner(System.in);
        String bookName = scanner.nextLine();
        int currentSize = bookList.getUsedSize();

        for (int i = 0; i < currentSize; i++) {

            Book book = bookList.getBook(i);
            if(book.getName().equals(bookName)){
                book.setState(false);
                System.out.println("归还成功");
                return;
            }
        }

        System.out.println("归还失败");
    }

}

ShowOpreation类

java 复制代码
public class ShowOpreation implements IOPeration{
    public void work(BookList bookList){
        System.out.println("显示图书");

        int currentSize = bookList.getUsedSize();
        for(int i = 0;i < currentSize; i++){
            Book book = bookList.getBook(i);
            System.out.println(book);
        }
    }
}
相关推荐
superman超哥10 小时前
Rust HashMap的哈希算法与冲突解决:高性能关联容器的内部机制
开发语言·后端·rust·哈希算法·编程语言·冲突解决·rust hashmap
刘一说10 小时前
腾讯位置服务JavaScript API GL与JavaScript API (V2)全面对比总结
开发语言·javascript·信息可视化·webgis
a程序小傲10 小时前
【Node】单线程的Node.js为什么可以实现多线程?
java·数据库·后端·面试·node.js
Aotman_11 小时前
JS 按照数组顺序对对象进行排序
开发语言·前端·javascript·vue.js·ui·ecmascript
indexsunny13 小时前
互联网大厂Java求职面试实战:Spring Boot微服务与Redis缓存场景解析
java·spring boot·redis·缓存·微服务·消息队列·电商
无心水13 小时前
【分布式利器:腾讯TSF】7、TSF高级部署策略全解析:蓝绿/灰度发布落地+Jenkins CI/CD集成(Java微服务实战)
java·人工智能·分布式·ci/cd·微服务·jenkins·腾讯tsf
28岁青春痘老男孩18 小时前
JDK8+SpringBoot2.x 升级 JDK 17 + Spring Boot 3.x
java·spring boot
方璧18 小时前
限流的算法
java·开发语言