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

Java实现简单图书操作系统思路讲解

目录

 1、分析图书系统设计到的各种类和类的属性

  2、编写代码

1、Book类

2、BookList 类

3、具体操作分析

4、用户分类

5、开始整合(最难)


先给大家展示一下完成后图书系统的样子

 接下来,主要讲解代码编写的思路,完整代码点击文字获取 图书小练习

 1、分析图书系统设计到的各种类和类的属性

写代码之前,我们先要大致抽象出来一些该有的类和类的属性。

在具体写代码的时候还会有一些部分添加

1)首先 图书系统 肯定要有 书,而我们要想准确描述一本书,我们就要创建一个书类(Book)

包含属性

  • 书名 name
  • 作者 author
  • 价格 price
  • 类型 type
  • 是否被借出 isBorrowed

2)有了书之后,就要有书架(用来存储书籍)。所以我们还要创建一个书架类 (BookList)

 包含属性

  • Book[] (存储书籍,可以要用数组来存储)

3)用户分类,我们的图书操作系统分为 【普通用户】和【管理员】,所以我们要创建 AdminUser类(管理员) 和 NormalUser 类(普通用户)

注意:不同的用户,打印的菜单不同,这里先提醒一下大家

4)各种操作类,我们还要创建一些来对书架进行操作(简称 操作类)。主要的操作如下

  1. 查找图书(FindOperation 类)
  2. 新增图书(AddOperation 类)  
  3. 删除图书(DelOperation 类)
  4. 显示图书(DisplayOperation 类)
  5. 归还图书(ReturnOperation 类)
  6. 借阅图书(BorrowOperation 类)
  7. 退出书架(ExitOperation 类)

以上我们就基本把这个图书操作系统各个部分分析完了,而为了方便我们管理,我们还要对这些类进行分门别类。

也就是说,我们在编写代码时,把不同的类放在不同包下,用包来对这些类进行封装

  2、编写代码

1、Book类

我们首先来写 Book 类,把图书的各种特性创建成员变量,这些成员变量用 private 修饰

    private String name;//书名
    private String author;//作者
    private int price;//价格
    private String type;//类型
    private boolean isBorrowed;//是否被借出
用 private 修饰体现封装

     同时因为这些成员变量是被 private 修饰,在类外不能获取,所以我们要写一系列 get 和 set 方法,方面我们类外获取和修改这些变量。

    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 isBorrowed() {return isBorrowed;}

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

        然后,构造 Book 实例时,为了方便给成员变量赋值,所以我们也可以写一个构造方法。为了方便显示 书 的内容,我们还要写一个 toString 方法

public Book(String name, String author, int price, String type) {
        this.name = name;
        this.author = author;
        this.price = price;
        this.type = type;
    }
    
public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                ((isBorrowed == true) ? "已经借出":"未借出")+
                '}';
    }

构造方法里面没有给 isBorrowed 赋值,是因为 isBorrowed 是 bollean 类型的变量,创建的初始值为 false,方便我们后续的操作。所以不用再给 isBorrowed 赋值

到这里 Book 类算是完成啦,接下来就是 BookList 类。 

 2、BookList 类

   单独的书的类型创建好了,现在就来创建一个 BookList 类用来存储书籍。

这个 BookList 就相当于 书架

   我这里用数组来存储多本书,创建一个 Book数组 类型的成员变量,存储容量大小为10

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

存储书籍也能用 ArrayList、LinkList等....这里为了方便理解,我用了数组 

   存储 书 的书架有了,那我们如何知道这个书架里面有多少本书呢?

    为了解决这个问题,再来创建一个成员变量来记录我们存储图书的数量

    private int usedSize;//实时记录,当前books这个数组当中有多少本书

在书架中,我们可能要取书、存书等操作。而这些操作其实就是对 BookList 类中数组进行的操作,所以我们要在类中写一些方法来完成这些操作供外界使用。 

  • 通过下标获取书
  • 在某位置下放书
  • 获取 书架 中书的个数
  • 修改 书架 中书的个数
    /**
     * @param pos pos一定是合法的
     * @return
     */
    public Book getBook(int pos){
        return books[pos];
    }

    /**
     * @param pos 此时pos一定是合法的
     * @param book 是你要放的书
     */
    public void setBooks(int pos,Book book){
        books[pos] = book;
    }
    
   /**
     * 实时获取当前书的个数
     * @return
     */
    public int getUsedSize(){return usedSize;}

    /**
     * 实时的修改当前书架上的书的个数
     */
    public void setUsedSize(int size){
        usedSize = size;
    }

为了方便我们后面的操作,当我们构造 BookList 对象时,先生成三本书

    public BookList(){
        books[0] = new Book("三国演义","罗贯中",19,"小说");
        books[1] = new Book("西游记","吴承恩",19,"小说");
        books[2] = new Book("红楼明","曹雪芹",19,"小说");
        usedSize = 3;
    }

3、具体操作分析

      这里我把把这些操作方法类全部都放到一个 operation 包下面!

      因为这些 “方法” 都是对 BookList进行操作,那我们是不是可以创建一个接口,来统一标准的规范

 0)IOperation 接口

public interface IOperation {
    void work(BookList bookList);
}

接下来,我们让具体的操作来实现这个接口 

        例如:添加图书 AddOperation 类

public class AddOperation implements IOperation{
    @Override
    public void work(BookList bookList) {
        System.out.println("添加图书");
    }
}

这里先不着急实现具体的业务逻辑,我们先把逻辑整理好 

其他的操作也是类似,这里就不在赘述了 

借阅图书 BorrowOperation

删除图书 DelOperation

展示图书 DisplayOperation

查找图书 FindOperation

归还图书 ReturnOperation

退出 ExitOperation

4、用户分类

我们的用户分为两种,一种是管理员,另一种是普通用户。

虽然他们的操作不同,但是都是属于用户这一类,所以我们可以写一个父类 User,在父类中 定义属性和方法,然后让子类继承。这样子类就不必重复写哪些操作

0)父类 User

public class User {
    protected String name;//用户名

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

    public abstract int menu();//打印菜单
    //因为管理员和普通用户的菜单内容不一样,所以在父类中 menu 方法我们可以直接写为抽象方法
}

1)子类 AdminUuser 和 NormalUser

        我们让子类 AdminUuser 和 NormalUser 继承 父类 User,这样我们就不用重复定义 name这个属性。

继承父类后,我们要提供一个构造方法来显示的帮助父类构造!!!

注意:不同用户菜单不同!

public class AdminUser extends User{
    public AdminUser(String name) {
        super(name);
    }

    public int menu(){
        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("请输入你的操作:");
        Scanner scanner = new Scanner(System.in);
        int choice = scanner.nextInt();
        return choice;
    }
    
}
public class NormalUser extends User{

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

    public int menu(){
        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("请输入你的操作:");
        Scanner scanner = new Scanner(System.in);
        int choice = scanner.nextInt();
        return choice;
    }
}

这里用户逻辑也基本实现啦,现在我们开始整合这些类

5、开始整合(最难)

这里我们新创建一个类 Main(这个类不在上面任何包内),创建一个 main方法。接下来我们将在该方法中整合所以部分。

第一步:我们首先要准备我们的图书

BookList bookList = new BookList(); //准备图书

 这里我们不用一本书一本的创建放到 bookList 中,因为在 BookList 实例化时就准备好了三本书

第二步:开始登陆

这里我创建一个 login 方法,然后在 main 中调用

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

        System.out.println("请输入你的姓名:1 -》管理员,0 -》普通用户");
        int choice = scanner.nextInt();

        if(choice == 1){
            return new AdminUser(name);
        }else {
            return new NormalUser(name);
        }

    }

 为什么 login 方法的返回值是 User?因为 AdminUser 类 和 NormalUser 类都是 User 的子类,不管我们选择哪个角色进行实例化,User 都能接收 【向上转型】

 在 main 方法中,同样用 User接收

//登陆-> user 这个引用 引用那个对象
User user = login();

第三步:调用菜单,把具体操作跟菜单结合

因为上面我们一下选择 user 的实例化对象是管理员还是普通用户,所以我们直接调用menu 方法显示出来的菜单内容也是不一样的。

        所以我们要在 AdminUser 类 和 NormalUser 类分别定义 menu方法

AdminUser 类中 menu() 方法

    
public int menu(){
        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("请输入你的操作:");
        Scanner scanner = new Scanner(System.in);
        int choice = scanner.nextInt();
        return choice;
    }

NormalUser 类中 menu() 方法

    public int menu(){
        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("请输入你的操作:");
        Scanner scanner = new Scanner(System.in);
        int choice = scanner.nextInt();
        return choice;
    }

到这里还没结束,我们回到 Main类中,我们选择的用户类型是用 父类 User 接收的,

所以我们需要 user对象来调用 menu()。

此时编译器就会报错,原因就是 User 类中没有定义 menu,所以我们还要在 User 类中写一下menu() 方法

public abstract int menu();

父类中的 menu方法不需要具体实现,定义为抽象类就行。

此时我们在用 user调用就不会出错了,menu() 方法会动态绑定!!!

【我们选的哪个就会打印哪个的菜单】

         然后我们创建一个变量来接收用户的选择

int choice = user.menu();//动态绑定

 我们来看不同用户的菜单,在管理员菜单中 ‘2’ 是新增图书,而在普通用户菜单菜单中 ‘2’ 是借阅图书。

现在问题来了,我们如何才能知道用户想要执行那个 ‘2’ 操作呢?

我们是不是可以让  AdminUuser 对象和 NormalUser 对象中分别存储好各种要执行的操作就可以了。

现在我们重新回到 User类中,添加一个成员

protected IOperation[]  iOperations;//此时并没有初始化和分配大小

然后分别在 AdminUuser 和 NormalUser 各自的抽象方法中各自初始化具体的内容

最后,在父类 User 中再定义一个具体调用哪个操作的方法

    public void doOperation(int choice, BookList bookList){
        this.iOperations[choice].work(bookList);
    }

这样我们就能根据用户选择来决定实现那种方法啦 

通过 choice 作为下标,来找到具体的执行类并执行类中的方法

 为什么 doOperation 方法分别定义在  AdminUuser 和 NormalUser 中?

        因为如果定义在  AdminUuser 和 NormalUser 中,在整合时 use 对象就无法调用 doOperation 方法。

到这我们的图书管理系统就整合完啦,具体代码大家可以在开头部分下载参考【下载免费的呦】

有错误的地方或者有讲解不明白的地方,希望大家能批评指正,别忘了点赞👍+收藏⭐️哦 

      😜  关注我!带来等多精彩🎉🎉

相关文章:

  • SpringBoot MVC使用Gson,序列化LocalDate,LocalDateTime
  • 戴尔G3-3579改固态散热
  • C3P0和Druid数据库连接池的使用
  • 2022中国消费者智能网联汽车数据安全和个人隐私意识与顾虑调查报告
  • Java 大文件分片上传
  • Redis未授权访问漏洞
  • Java 修饰符 private、default、protected、public 的应用实例 (方法)
  • Java 多线程:锁(一)
  • VMware 搭建linux操作系统,入门必看
  • 2022牛客多校(三)
  • 阿里云服务器和腾讯云服务器哪个更好?多维度对比得出了结论
  • sqli-labs(less-1)
  • 【Ubuntu】gcc与Makefile操作
  • Python零基础入门篇 · 21】:构造函数、类属性和实例属性的访问
  • Invalid bound statement (not found)出现的原因和解决方法
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Git的一些常用操作
  • HTTP 简介
  • Java Agent 学习笔记
  • MaxCompute访问TableStore(OTS) 数据
  • React16时代,该用什么姿势写 React ?
  • spark本地环境的搭建到运行第一个spark程序
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • webpack入门学习手记(二)
  • windows下mongoDB的环境配置
  • 机器学习中为什么要做归一化normalization
  • 马上搞懂 GeoJSON
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 系统认识JavaScript正则表达式
  • 在Mac OS X上安装 Ruby运行环境
  • ​MySQL主从复制一致性检测
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • #git 撤消对文件的更改
  • $.ajax()参数及用法
  • (C++20) consteval立即函数
  • (C语言)逆序输出字符串
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (四)模仿学习-完成后台管理页面查询
  • (转)拼包函数及网络封包的异常处理(含代码)
  • (转)人的集合论——移山之道
  • (转)为C# Windows服务添加安装程序
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .NET中两种OCR方式对比
  • []常用AT命令解释()
  • [C#]OpenCvSharp结合yolov8-face实现L2CS-Net眼睛注视方向估计或者人脸朝向估计
  • [c]统计数字
  • [CentOs7]iptables防火墙安装与设置
  • [CTO札记]如何测试用户接受度?
  • [EFI]MSI GF63 Thin 9SCXR电脑 Hackintosh 黑苹果efi引导文件