• java之《图书管理系统》庖丁解牛


    🎇🎇🎇作者:
    @小鱼不会骑车
    🎆🎆🎆专栏:
    《java练级之旅》
    🎓🎓🎓个人简介:
    一名专科大一在读的小比特,努力学习编程是我唯一的出路😎😎😎
    在这里插入图片描述

    前言

    关于这个《图书管理系统》,其中涉及到了我们很多以前的知识,有数组,引用类型,抽象类,多态,以及接口等等,但是即使是我们学习过那些基础的知识,想要单独的去实现这个系统也是有些麻烦,甚至是有一些困难,包括小鱼,也是在接触到这个系统的时候,踩了好多坑,犯了好多错,这次小鱼将会对这个《图书管理系统》庖丁解牛,大家也会更容易理解的
    在这里插入图片描述

    在这里插入图片描述

    🍁第一部分(简单介绍)

    我们写这个《图书管理系统》可以简答的分为两类,管理员类和读者类,他们分别对应这不同的权限,具有不同的功能,例如下图
    在这里插入图片描述
    那么我们应该思考实体对象也就是用户和图书!
    在这里插入图片描述
    这时候我们就该建表了,例如用户表,书表,功能表
    在这里插入图片描述
    到这里我们的表建好了之后,就需要根据需求,去用代码实现相应的功能,例如登录如何登录,借书怎么去借,借完了书,书的状态又是什么,以及如何用逻辑来实现书的增删查改等等操作。
    下面给大家看一下小鱼实现的代码运行的结果,不同的身份有不同的界面
    管理员的界面
    在这里插入图片描述
    读者的界面

    在这里插入图片描述
    我们先不去管这些功能是如何具体的实现,我们先将大体的框架实现出来,

    🍁第二部分(大体框架)

    🌿实现《用户表》

    🍂实现菜单

    1.这是第一步,仅仅只是把最初始的页面完成一下,这里涉及到的知识不多,大家简单看一下(返回类型先不去管)

        public static User longin() {//返回类型先不去管
            Scanner scanner=new Scanner(System.in);
            System.out.print("请输入你的姓名: ");
            String name=scanner.next();
            System.out.println("请选择你的身份:");
            System.out.println("1.管理员  2. 普通用户 ");
            int n=scanner.nextInt();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.这一部分就重要了,需要根据选择的身份,来判断具体有什么功能,并且打印在屏幕上。代码入下,

     while(true) {
                if(n==1) {
                    //管理员
                    return new Adminuser(name);//看这里!!!
                } else if (n==2){
                    //普通用户
                    return new Normaluser(name);//还有这!!!
                } else {
                    System.out.println("输入错误,请重新输入");
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    🍂实现父类User

    注意!!!User是Adminuser和Normaluser的父类
    3.我们无论是管理员还是普通用户,都需要输入姓名,并且拥有各自对应的菜单,那么我们可以在User这个父类中创建姓名这个成员变量,并且由于我们的菜单并不需要在父类中具体实现,我们便可以将菜单设置为抽象方法也就是被abstract修饰。
    (记得看注释!!!)

    public abstract class User {
        private String name;//用户名,由于是private修饰,需要对外的接口
        User(String name) {//构造方法,实例化对象时便初始化姓名
            this.name = name;
        }
        public  abstract void mnum();//菜单
        public String getName() {//输出接口
            return name;
        }
        public void setName(String name) {//输入接口
            this.name = name;
        }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    🍂实现子类用户

    🍄Adminuser(管理类)

    4.我们先介绍管理员类(Adminuser)

    public class Adminuser extends User {//继承父类
      public Adminuser(String name) {//构造方法
            super(name);
        }
        String name=getName();//接收父类的属性
        @Override
        public void mnum() {//在管理员这里实现菜单
            Scanner scanner=new Scanner(System.in);
            System.out.println("hello "+name+" 欢迎来到图书系统");
            System.out.println("********************");
            System.out.println("1.查找图书");
            System.out.println("2.增加图书");
            System.out.println("3.删除图书");
            System.out.println("4.显示图书");
            System.out.println("5.修改图书");
            System.out.println("0.退出系统");
            System.out.println("********************");
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    🍄读者类(Normaluser)

    5.读者类(Normaluser)

    public class Normaluser extends User{//继承父类
       public Normaluser(String name) {//构造方法
            super(name);
        }
          String name=getName();//接收父类的属性
        @Override
        public void mnum() {
            Scanner scanner=new Scanner(System.in);
            System.out.println("hello "+name+" 欢迎来到图书系统");
            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("********************");
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    具体的菜单我们实现了,接下来我们就是运行一下,看看我们的结果是否是和我们预想的一样

    🍄运行代码

    Main文件代码(后面还会添加新内容)

    public class Main {
    
        public static User longin() {//返回类型先不去管
            Scanner scanner=new Scanner(System.in);
            System.out.print("请输入你的姓名: ");
            String name=scanner.next();
            System.out.println("请选择你的身份:");
            System.out.println("1.管理员  2. 普通用户 ");
            int n=scanner.nextInt();
            while(true) {
                if(n==1) {
                    //管理员
                    return new Adminuser(name);//看这里!!!
                } else if (n==2){
                    //普通用户
                    return new Normaluser(name);//还有这!!!
                } else {
                    System.out.println("输入错误,请重新输入");
                }
            }
        }
        public static void main(String[] args) {
               User user= longin();
                user.mnum();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    由于我们两个的返回值类型是不一样的,编译器无法分辨去返回哪个值,于是就用他们的父类作为返回值类型,便可以解决这个问题,并且返回的类型被进行了类型提升的操作,于是我们可以用User user=longin();接收这个返回值,并去调用他们的菜单方法。
    在这里插入图片描述

    🌿实现《书表》

    🍂实现Book

    再来复习一下,我们前面讲到了,一个书,需要书名,作者,价格,类型,是否被借出这五个属性,那么我们就优先实现这五个,并且我想将我的书的信息进行封装,那么我就需要用private修饰并且预留出接口,用于被外界访问。自己实现toString这个方法,后面涉及到的三目操作符是用来判断书是否被借出如果是true那就是被借出,否则就是没有被借出

    public class Book {
        private String name;//书名
        private String author;//作者
        private int  price;//价格
        private String type;//类型
        private boolean isBorrowde;//是否被借出
    //调用这个构造方法来对这本书进行初始化,
    //因为boolean本身默认为false,所以不需要再去进行初始化。
        public Book(String name, String author, int price, String type) {
            this.name = name;
            this.author = author;
            this.price = price;
            this.type = type;
        }
    
        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 isBorrowde() {//状态的接口
            return isBorrowde;
        }
    
        public void setBorrowde(boolean borrowde) {
            isBorrowde = borrowde;
        }
    
    //自己实现toString这个方法,
    //后面涉及到的三目操作符是用来判断书是否被借出
    //如果是true那就是被借出,否则就是没有被借出
        @Override
        public String toString() {
            return "Book{" +
                    "name='" + name + '\'' +
                    ", author='" + author + '\'' +
                    ", price=" + price +
                    ", type='" + type + '\'' +
                    ", 该图书" + ((isBorrowde==true)?" 被借出":" 未被借出") +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    🍂实现BookList

    那么我们既然有书了,那么我们书的信息保存到哪里呢?当然是书架!这就需要涉及到数组了,我们用数组来保存这个书的信息,这样我们就可以保存10本,20本等等
    但是我们思考一个问题啊,我们这个数组的类型,究竟是什么类型呢?我们的书有5个成员变量,还都是不同类型的,该如何保存呢?那就涉及到了引用类型,我们可以以书为一个类型创建一个数组,如下代码(千万认真看,很重要)

    public class BookList {
        private Book[] books=new Book[10];//初始化书这个数组
        private int  userSize;//书的个数
    //在最末位置增加新书
        public void setBooks(Book books) {
            this.books[userSize] = books;
        }
    //在指定位置修改书籍
        public void setBooks(Book books,int size) {
    
            this.books[size] = books;
        }
    //返回书的个数
        public int getUserSize() {
            return userSize;
        }
    //返回对应下标的书
        public Book getBooks(int pos) {
            return books[pos];
        }
    //修改书的个数
        public void setUserSize(int userSize) {
            this.userSize = userSize;
        }
        //初始化我们的书籍
        public BookList(){
            books[0]=new Book("三国演义","罗贯中",18,"小说");
            books[1]=new Book("西游记","吴承恩",18,"小说");
            books[2]=new Book("红楼梦","曹雪芹",18,"小说");
            this.userSize=3;//初始化我们的书的个数
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    书,一定会记录有多少本,那么我们就用userSize去记录有多少本书,并且我们的数组依旧是被private修饰的权限,只能在自己的类中访问,于是就创建数组的接口以及数组个数的接口。
    那么既然我们的《书表》创建完成,下面就是重中之重!!!

    🍁第三部分(实现细节)《功能表》

    细心的同学在最开始就会发现,我实现了一个接口,接口里的内容是抽象方法编译器默认将类型改为public abstract,也就是我们后续所有对书进行的操作,都是在重写这个方法的方法中进行的。具体关于抽象类和接口可以看我之前的一篇博客抽象类和接口链接
    在这里插入图片描述
    我们先将功能的大体框架给大家看一下,最后一个是接口
    在这里插入图片描述
    在这里插入图片描述

    🍂接口数组

    前面大体框架也介绍了,那我们如何根据我们的需要去调用对应的类呢?这就体现了接口的好处,我在上面的图中,每一个类都实现了IOperation这个接口,那么也就意味着,我们所有的实现这个接口的类,都可以类型提升为IOperation,那我们就可以创建一个类的数组!!!
    由于不同用户有不同的需求,所以我们可以在管理员和读者中分别实现这个类的数组(这个思路真的很牛,大家认真看!!!)

    在这里插入图片描述
    在这里插入图片描述
    并且数组初始化是放在构造方法中的,这样就可以在实例化对象时,就初始化完成这个数组。
    我们先来实现一下父类中doWork的方法,并且进行解析
    在这里插入图片描述

    那么该如何调用这个数组呢?
    在这里插入图片描述
    现在我们就可以通过这个方法去调用他们所对应的数组的类
    运行结果
    在这里插入图片描述

    🍂AddOperation(增加图书)

    我们如果想要是增加图书的话,就需要对这个图书数组进行修改,并且将图书的个数进行+1的操作,下面是代码

    public class AddOperation implements IOperation{
    
        @Override
        public void work(BookList books) {
            Scanner scanner=new Scanner(System.in);
            System.out.println("增加图书!");
            System.out.println("输入书名:");
            String name=scanner.next();
            System.out.println("请输入作者:");
            String author=scanner.next();
            System.out.println("请输入价格:");
            int price=scanner.nextInt();
            System.out.println("请输入类型:");
            String type=scanner.next();
            //调用Book的构造方法,初始化一本书
            Book book=new Book(name,author,price,type);//
            for (int i=0;i<books.getUserSize();i++) {
                Book book1= books.getBooks(i);//将返回的引用给book
                if(book1.getName().equals(name))//用book去调用Book类的getName
                {
                    System.out.println("要添加的书已经存在,不能添加");
                    return;
                }
            }
            books.setBooks(book);
            books.setUserSize(books.getUserSize()+1);
            System.out.println("添加成功");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    用代码来讲不太方便,小鱼画图给大家讲解吧。
    1.初始化一个Book类
    在这里插入图片描述
    2.监测要添加的书是否存在,如果存在,则直接返回,不再新增该图书,
    在这里插入图片描述
    3.如果该图书不存在,大家对应着BookList类里面的方法看。
    在这里插入图片描述
    就这样,我们的图书新增成功,运行结果如下
    在这里插入图片描述

    在这里插入图片描述
    大家也可以自己实践一下,千万注意,我们设置的价格是整形的,如果想输入小数,记得改成浮点型。

    🍂DelOperation(删除图书)

    🍄简单介绍

    由于我们想去删除的图书是在数组里面,这就涉及到了数组的删除,在不改变原有顺序的情况,我们可以通过移动数组的元素来达到这一需求,先用简单的数字举例,
    在这里插入图片描述
    如何做到呢?我们可以通过遍历数组找到这个3,然后将3后面的元素全部往前移动,最后会出现这种情况
    在这里插入图片描述
    最后会多出来一个末尾元素,我们需要将这个末尾元素置为null,并且数组长度-1,这样我们就会得到一个和我们预期相符合的数组(具体步骤)
    在这里插入图片描述
    在此之前我们还需要考虑数组的类型,数组如何从后面一层一层往前覆盖,那么理论存在,实践开始

    🍄构建大概过程

    画图解释!!!
    第一步(构建大体的框架)
    在这里插入图片描述

    🍄详细解析如何修改数组(在不改变顺序的前提)

    第二步(详细解释如何得到该数组的长度,以及如何访问到该数组并且进行修改)
    在这里插入图片描述
    不断的通过判断名字是否相同,如果不同i++,如果相同进入if()
    进入if()后进行元素的删除,并且根据循环,不断的将后面的一个元素覆盖之前的元素,直到我j==cur-1,才停止循环(注意!!!如果我的判断条件不是cur-1可能会存在越界的问题)
    在这里插入图片描述

    🍄将删除元素后的数组进行最后的处理

    第三步(如何将数组最后的元素置为null,如何将数组的长度-1)
    在这里插入图片描述
    运行结果
    在这里插入图片描述

    🍂FindOperation(查找图书)

    我们写完了这两个比较难的功能,剩下的就会简单些许,小鱼为了不水文章,也会用通俗的文字表达。
    大体思路依旧是可以通过遍历这个数组,通过对比名字来查找这本图书,

    public class FindOperation implements IOperation{
        @Override
        public void work(BookList books) {
            Scanner scanner=new Scanner(System.in);
            System.out.println("查找图书!");
            System.out.println("请输入书名: ");
            String name=scanner.next();
            for (int i=0;i<books.getUserSize();i++) {
                Book book= books.getBooks(i);//将返回的引用给book
                if(book.getName().equals(name))//用book去调用Book类的getName
                {
                    System.out.println(books.getBooks(i));
                    return;
                }
            }
            System.out.println("没有找到该图书!");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    所以就是通过一个for遍历整个数组,然后通过if来进行判断,如果存在,就将这本书打印,如果不存在,那就是找不到该图书,其中那些方法的运用在增,删中都有用到,大家可以参考上面的

    🍂ReviseOperation(修改图书)

    修改图书分为几步?先查找这个图书存不存在,再创建一个新书,最后将新书的引用覆盖原有要被修改图书的引用。
    在这里插入图片描述

    🍂BrrowOperation(借阅图书)

    如何借阅图书呢?我们的图书不是都有一个状态嘛,true或者false,在默认的情况,我们的书是未被借出的,也就是false,当我们的书被借出时,我们就可以对其进行修改,改为true,这就是我们的一个思路
    依旧是查找该图书,对该书的状态进行修改,并且当我们的书的状态是true时,就说明该书已经借出来了,无法再借阅,也就可以直接退出这个操作了
    在这里插入图片描述

    🍂ReturOperation(归还图书)

    同上,一样的思路,遍历数组,找到名字符合的,直接将其修改为false.
    在这里插入图片描述

    🍂ShowOperation(打印所有图书)

    马上结束!!!
    打印图书嘛,遍历数组,将每一个图书都进行打印,还是有一个小知识点,前提讲到了小鱼将toString重写了,所以我们打印时,调用的是我们自己的toString

    public class ShowOperation implements IOperation{
        @Override
        public void work(BookList books) {
            System.out.println("显示图书!");
            for (int i=0;i<books.getUserSize();i++) {
                System.out.println(books.getBooks(i));
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    最后输出
    在这里插入图片描述

    🍂最后一个退出操作系统!!!!

    public class ExitOperation implements IOperation {
        @Override
        public void work(BookList books) {
            System.out.println("退出系统!");
            System.exit(0);//为什么是0?
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在系统中默认返回0是正常退出
    在这里插入图片描述

  • 相关阅读:
    单商户商城系统功能拆解30—营销中心—积分签到
    目标检测—安全帽检测实践
    Ubuntu 12.04增加右键命令:在终端中打开增加打开文件
    Windows10打开应用总是会弹出提示窗口的解决方法
    Spring Boot 实现各种参数校验,建议收藏!
    【数据结构】面试OJ题——带环链表(数学推论)
    04_瑞萨GUI(LVGL)移植实战教程之驱动LCD屏(SPI)
    【IDE】Navicat使用技巧
    PDEBench-AI求解微分方程新基准
    【C】语言文件操作(一)
  • 原文地址:https://blog.csdn.net/xiaoyubuhuiqiche/article/details/127954488