邦布带你从零开始实现图书管理系统(java版)

news2024/9/22 1:15:04

今天我们来从零开始实现图书管理系统。

图书管理系统

来看我们的具体的实现,上述视频。

我们首先来实现框架,我们要实现图书管理系统,首先要搭框架。

我们首先定义一个书包,在书包中定义一个书类和一个书架类,再定义一个用户包,其中包含用户类,管理者类,普通用户类,在定义一个工具包来实现具体操作,定义一个主函数。

我们先来实现Book类

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

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

    public void setBorrowed(boolean borrowed) {
        isBorrowed = borrowed;
    }
    
    public String toString(){
        return "Book{" + "姓名:" + name + '/' + 
                "作者:" + author + '/' + "价格:" +
                price + '/' + "类型" + type + '/'
                + ((isBorrowed==true)?"已借阅":"未借出");
    }
}

我们对书进行描述的类,包含书名,作者名,价格,类型,和书是否被借出的状态,我们提供对name,author,price,type初始化的构造方法,为什么不对isborrowed进行初始化呢,因为boolean开始就是false,我们在进行ALT + Insert对所有字段提供getter and setter因为我们的权限是private。

最后对toString函数进行重写,来保证我们使用System.out.println()的时候可以输出我们book,对象的全部属性,那么这个((isborrowed)?已借阅":"未借出")是什么呢,我们isBorrowed默认是false所以默认是未借出,当我们后期修改isBorrow的时候就能达到true是已借阅的情况了。用的条件表达式,如果isBorrowed==true那么就是已借阅否则就是未借出。

我们下面实现书架类

public class BookList {
    Book[] Books = new Book[10];
    private int usedSize;
    public BookList(){
        this.Books[0] = new Book("三国演义","罗贯中",20,"小说");
        this.Books[1] = new Book("西游记","吴承恩",38,"小说");
        this.Books[2] = new Book("红楼梦","曹雪芹",30,"小说");
        this.usedSize=3;
    }

    public int getUsedSize() {
        return usedSize;
    }

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

    public Book[] getBooks() {
        return Books;
    }

    public void setBooks(Book[] books) {
        Books = books;
    }
}

我们首先创建一个数组,我们用书类来定义一个书类数组,类似实现书架的功能,再定义usedSize来表示书架上到底有多少书,再提供构造方法的时候我们除了初始化我们的uesdSize,还要再Books数组中放入3本书来保证我们创建书架的时候就已经有书了,再提供Books数组和usedSize的Getter和Setter,Books数组的Gette和Setter有问题,我们后面再说

我们再来定义main类来跑程序

我们看我们运行的时候,

会有一个登录界面,我们在Main类中实现它

public class Main {
    public static void login(){
        
    }
    public static void main(String[] args) {
        BookList bookList = new BookList();
        login();
    }
}

我们在Main类中创建了一个书架对象,生成了刚才创建的三本书,我们通过login函数来实现登录界面

    public static void login(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的姓名");
        String name = scanner.nextLine();
        System.out.println("请输入你的身份 1, 管理员 2, 用户");
        String choice = scanner.nextLine();
    }

我们实现了输入并用name记住了姓名,用choice记住了选择

我们还可以去设计密码来限制是否为管理员登入

    public static void login(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的姓名");
        String name = scanner.nextLine();
        System.out.println("请输入你的身份 1, 管理员 2, 用户");
        int choice = scanner.nextInt();
        if(choice==1){
            while (true){
                System.out.println("请输入密码");
                int count = scanner.nextInt();
                if(count==123456){
                    System.out.println("密码正确");
                    return;//进入管理员菜单
                }
                else{
                    System.out.println("是否重新输入密码 1,是 2,否");
                    int count2 = scanner.nextInt();
                    if(count2==1){
                        continue;
                    }
                    else {
                        break;
                    }
                }
            }
        }
        return;

    }

我们用循环和if语句来实现个简单的密码限制,这里就不过多描述了,我们既然有了选择,就要实现两个类来创建不同的对象,

这样就实现了两个不同的用户菜单,这里菜单名字忘改了,但是他们对书架操作的权限是不同的

我们现在来实现这个用户类

public abstract class User {
    protected String name;
    public User(String name){
        this.name = name;
    }
    
    public abstract int menu();
}

我们创建了三个类,User是我们的父类,而其他两个是我们的子类,为什么要这样设计呢,因为我们在Main类运行代码的时候,调用一个父类User来利用多态,对字类重写的方法进行调用会更好,就刚才我们进行的选择,我们会创建不同的对象,密码正确我们会创建AdminUser对象,NormalUser对象,而使用继承我们可以直接把他向上转型为User类,用Uesr类来调用,话不多说我们直接上代码

先导入我们需要的包,

在子类AdminUser中操作

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

    @Override
    public int menu() {
        System.out.println("欢迎" + name + "管理员" + "来到电子图书馆");
        Scanner scanner = new Scanner(System.in);
        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("****************");
        return 0;
    }
}

在之前的Main中如果是管理员的话返回一个新的管理员对象,但是问题来了我们返回值不是void吗、

我们将返回值给上User这下不彻底穿起来了,我们就可以用user来访问管理员对象了,使用了我们的多态

public class NormalUser extends User {
    public NormalUser(String name) {
        super(name);
    }
    public int menu() {
        System.out.println("欢迎" + name + "用户" + "来到电子图书馆");
        Scanner scanner = new Scanner(System.in);
        System.out.println("****用户菜单****");
        System.out.println("1. 借阅图书");
        System.out.println("2. 归还图书");
        System.out.println("3. 查找图书");
        System.out.println("0. 退出系统");
        System.out.println("****************");
        return 0;
    }
}

在把用户的写了,我们再主类中去调用

再完整的展示下login函数

    public static User login(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的姓名");
        String name = scanner.nextLine();
        System.out.println("请输入你的身份 1, 管理员 2, 用户");
        int choice = scanner.nextInt();
        if(choice==1){
            while (true){
                System.out.println("请输入密码");
                int count = scanner.nextInt();
                if(count==123456){
                    System.out.println("密码正确");
                    return new AdminUser(name);//进入管理员菜单
                }
                else{
                    System.out.println("是否重新输入密码 1,是 2,否");
                    int count2 = scanner.nextInt();
                    if(count2==1){
                        continue;
                    }
                    else {
                        break;
                    }
                }
            }
        }
        return new NormalUser(name);
    }

可以根据不同的选择返回管理员对象,或者用户对象

    public static void main(String[] args) {
        BookList bookList = new BookList();
        User user = login();
        while(true){
            user.menu();
        }
    }

我们就可以用父类user 来接收我们传过来的对象,发生了向上转型,我们可以通过user来调用我们在子类中重写的menu方法来显示不同的菜单

我们这时候运行就会显示两种不同的菜单,可以会有同学不明白为啥meun函数返回值是int,因为就要进行我们接下来的操作对每个选项的实现,所以在菜单界面我们就要接受我们选择的选项

我们在Main类中接收我们的选择

接下来就要实现具体操作。

我们在工具类进行操作,想想我们要怎么通过菜单的调用就能调用出具体的方法呢,

我们定义了这些类,每个类包含了对应的方法,还是那个问题,怎么通过菜单来访问对应的方法呢,最直观的就是类中有这些方法,这时我们就要用到接口了,让每个操作都用到了这个接口,而我们的管理员类和普通用户类中让他有接口的数组,这个用户中有哪个操作接口数组中就包含哪个。话不多说,我们继续进行操作

我们创建一个接口

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

让这个接口包含对书架操作的功能

让其他所有操作都包含这个接口

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

后面的就不一一列举了

我们在父类User中创建一个接口数组

public class NormalUser extends User {
    public NormalUser(String name) {
        super(name);
        this.IOPerations = new IOPeration[]{
                new ExitOPeration(),
                new BorrowOPeration(),
                new ReturnOPeration(),
                new FindOPeration()
        };
    }
    public int menu() {
        System.out.println("欢迎" + name + "用户" + "来到电子图书馆");
        Scanner scanner = new Scanner(System.in);
        System.out.println("****用户菜单****");
        System.out.println("1. 借阅图书");
        System.out.println("2. 归还图书");
        System.out.println("3. 查找图书");
        System.out.println("0. 退出系统");
        System.out.println("****************");
        System.out.println("请输入您的操作");
        int choice = scanner.nextInt();
        return choice;
    }
}

这样普通用户类就包含了他所需要的功能,我们的普通用户也彻底定义完了

public class AdminUser extends User{
    public AdminUser(String name){
        super(name);
        this.IOPerations = new IOPeration[]{
                new ExitOPeration(),
                new AddOPeration(),
                new DelOPeration(),
                new FindOPeration(),
                new ShowOPeration()
        };
    }

    @Override
    public int menu() {
        System.out.println("欢迎" + name + "管理员" + "来到电子图书馆");
        Scanner scanner = new Scanner(System.in);
        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("****************");
        System.out.println("请输入您的操作");
        int choice = scanner.nextInt();
        return choice;
    }
}

管理员用户我们也彻底定义完了,接下来就是实现用户对每个操作的调用我们首先要解决遗留问题

就是刚才我们对书架中的Getter和Setter不合理

我们想得到的是具体的书,放置书到书架具体的位置

    public Book getBooks(int pos) {
        return Books[pos];
    }

    public void setBooks(int pos, Book book) {
        Books[pos] = book;
    }

父类用户中

    public void DoOPeration(int choice, BookList bookList){
        IOPerations[choice].work(bookList);
    }

主类中

    public static void main(String[] args) {
        BookList bookList = new BookList();
        User user = login();
        while(true){
            int choice = user.menu();
            user.DoOPeration(choice,bookList);
        }
    }

这样我们就能在具体菜单中根据选择中进行具体的操作了

其他的我们就不一一展示了,接下来就是我们对操作的具体实现了,马上结束了不用心急。

1,结束类方法

public class ExitOPeration implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("退出系统");
        System.exit(0);
    }
}

直接System.exit(0)意思为程序正常退出

2,查找类方法

public class FindOPeration implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("查找图书");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你要查找的书名");
        String name = scanner.nextLine();
        int count = bookList.getUsedSize();
        for (int i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            if (book.getName().equals(name)){
                System.out.println(book);
                return;
            }
        }
        System.out.println("没有这本书");
    }
}

我们使用循环进行比较即可,如果name和我们book中的name相同就可以输出了

3,添加类方法

    public Book[] getbooksize(){
        return Books;
    }

在书架booklist中定义一个得到数组的函数,方便我们获得长度,因为我们在进行添加书的时候要判断书架是否满了。再创建一个book对象把新输入的属性,生成一本新的数,在把书放到书架上,之后记录书多了一本。

public class AddOPeration implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("添加图书");
        Scanner scanner = new Scanner(System.in);
        int size = bookList.getUsedSize();
        int size2 = bookList.getbooksize().length;
        if(size2==size){
            System.out.println("书架满了,无法添加");
        }
        else {
            System.out.println("请输入你要添加的书名");
            String name = 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(name,author,price,type);
            bookList.setBooks(size,book);
            bookList.setUsedSize(size+1);
        }
    }
}

4,借阅类方法

在借阅方法中还是一样我们把查找的方法拿来,其实都是利用查找的方法,再扩展,

如果找到了,就把book的属性改为true就是已借出。

public class BorrowOPeration implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("借阅图书");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你要借阅的书名");
        String name = scanner.nextLine();
        int count = bookList.getUsedSize();
        for (int i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            if (book.getName().equals(name)){
                if(book.isBorrowed()==false){
                    book.setBorrowed(true);
                    System.out.println("借阅成功");
                    return;
                }
                else {
                    System.out.println("书已经被借走了");
                    return;
                }
            }
            else{
                System.out.println("没有这本书");
            }
        }
    }
}

5,归还类方法

和借阅一模一样,就改下书的isBorrowed状态就行

public class ReturnOPeration implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("归还图书");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你要归还的书名");
        String name = scanner.nextLine();
        int count = bookList.getUsedSize();
        for (int i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            if (book.getName().equals(name)){
                if(book.isBorrowed()==true){
                    book.setBorrowed(false);
                    System.out.println("归还成功");
                    return;
                }
                else {
                    System.out.println("书已经归还了");
                    return;
                }
            }
            else{
                System.out.println("没有这本书");
            }
        }
    }
}

6,展示类方法

更简单了,我们直接循环遍历我们的书架就行了

public class ShowOPeration implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("展示图书");
        int count = bookList.getUsedSize();
        for (int i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            System.out.println(book);
        }
    }
}

7,删除类方法

public class DelOPeration implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("删除图书");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你要删除的书名");
        String name = scanner.nextLine();
        int pos = -1;
        int i = 0;
        int count = bookList.getUsedSize();
        for (i=0; i < count; i++) {
            Book book = bookList.getBooks(i);
            if (book.getName().equals(name)){
                break;
            }
        }
        if (count==i){
            System.out.println("你要删除的书不存在");
            return;
        }
        for (int j = pos; j < count-1; j++) {
            Book book = bookList.getBooks(j+1);
            bookList.setBooks(j,book);
            System.out.println("删除成功");
            bookList.setUsedSize(count-1);
            bookList.setBooks(count-1,null);
        }
    }
}

我们还是利用查找,找到了之后,利用顺序表尾删的方法就可以了,一个一个覆盖,减少书架usedsize的声明即可。

下面放上源码来方便大家学习

博客结合的通讯录 · 75122bd · 王涛c语言/test_c_study - Gitee.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1953017.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI大模型写的高考作文,你觉得怎么样?

下方为2024年高考新课标I卷语文作文题目&#xff0c;接下来将使用Chatgpt、文心一言、讯飞星火等众多AI大模型来写这篇高考作文 Chatgpt 标题&#xff1a;问题的演变与思考 随着互联网和人工智能技术的飞速发展&#xff0c;我们获得信息的方式和速度发生了前所未有的变化。曾经…

用PyTorch从零开始编写DeepSeek-V2

DeepSeek-V2是一个强大的开源混合专家&#xff08;MoE&#xff09;语言模型&#xff0c;通过创新的Transformer架构实现了经济高效的训练和推理。该模型总共拥有2360亿参数&#xff0c;其中每个令牌激活21亿参数&#xff0c;支持最大128K令牌的上下文长度。 在开源模型中&…

C嘎嘎浅谈模板

这篇文章给大家介绍一下c嘎嘎内存管理和模板&#xff0c;那么我们直接进入正题 c/c的程序内存分布 这里的了解一下即可 new和delete的定义和操作 格式&#xff1a;类型* 对象名 new 类型&#xff1b; 数组(对象)定义格式&#xff1a;类型* 对象名 new 类型[元素个数]&…

【安卓开发】【Android】如何进行真机调试【注意事项】

一、所需原料 1、电脑&#xff08;安装有Android Studio开发工具&#xff09;&#xff1a; 2、安卓操作系统手机&#xff1a;笔者演示所用机型为huawei rongyao50&#xff0c;型号为NTU-AN00&#xff1a; 3、数据线&#xff08;usb-typeA&#xff09;一根。 二、操作步骤 1…

支持向量机回归及其应用(附Python 案例代码)

使用支持向量机回归估计房价 让我们看看如何使用支持向量机&#xff08;SVM&#xff09;的概念构建一个回归器来估计房价。我们将使用sklearn中提供的数据集&#xff0c;其中每个数据点由13个属性定义。我们的目标是根据这些属性估计房价。 引言 支持向量回归&#xff08;SV…

IndexError: index 0 is out of bounds for axis 1 with size 0

IndexError: index 0 is out of bounds for axis 1 with size 0 目录 IndexError: index 0 is out of bounds for axis 1 with size 0 【常见模块错误】 【解决方案】 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#…

Linux网络工具“瑞士军刀“集合

一、背景 平常我们在进行Linux服务器相关运维的时候&#xff0c;总会遇到一些网络相关的问题。我们可以借助这些小巧、功能强悍的工具帮助我们排查问题、解决问题。 下面结合之前的一些使用经验为大家介绍一下一些经典应用场景下&#xff0c;这个网络命令工具如何使用的。例如怎…

关于Redis(热点数据缓存,分布式锁,缓存安全(穿透,击穿,雪崩));

热点数据缓存: 为了把一些经常访问的数据&#xff0c;放入缓存中以减少对数据库的访问频率。从而减少数据库的压力&#xff0c;提高程序的性能。【内存中存储】成为缓存; 缓存适合存放的数据: 查询频率高且修改频率低 数据安全性低 作为缓存的组件: redis组件 memory组件 e…

大模型算法备案流程最详细说明【流程+附件】

文章目录 一、语料安全评估 二、黑盒测试 三、模型安全措施评估 四、性能评估 五、性能评估 六、安全性评估 七、可解释性评估 八、法律和合规性评估 九、应急管理措施 十、材料准备 十一、【线下流程】大模型备案线下详细步骤说明 十二、【线上流程】算法备案填报…

手把手教小白微信小程序开发(超详细保姆式教程)

注册&#xff1a;微信公众平台 -> 立即注册 ->小程序 AppID(小程序ID) wx05c13b331acc9d01 AppSecret(小程序密钥) 4f8232c7bbd4801e58a166d72e92e529 安装 微信开发者工具 &#xff0c;扫描就可以登录 设置&#xff1a;右上角设置 ->外观浅色&#xff0c;代理&am…

C++通过进程句柄、进程id或进程名去杀掉进程(附完整源码)

目录 1、通过进程句柄去杀进程 2、通过进程id去杀进程 3、通过进程名去杀进程 C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931Windows C++ 软件开发从入门到精通(专栏文章,持续更…

普中51单片机:蜂鸣器的简单使用(十一)

文章目录 引言蜂鸣器的分类工作原理无源蜂鸣器压电式蜂鸣器&#xff1a;电磁式蜂鸣器&#xff1a; 电路符号及应用代码演示——无源蜂鸣器 引言 蜂鸣器是一种常见的电子音响器件&#xff0c;广泛应用于各种电子产品中。它们能够发出不同频率的声音&#xff0c;用于警报、提醒、…

AI软件测试|人工智能测试中对抗样本生成攻略

从医疗诊断、自动驾驶到智能家居&#xff0c;人工智能技术为各个行业领域带来无限可能的同时&#xff0c;挑战也日益显现。特别是在人工智能安全领域&#xff0c;随着恶意攻击和数据欺骗的不断演变&#xff0c;确保AI系统的安全性和可靠性成为亟需解决的重要问题&#xff0c;对…

【游戏制作】使用Python创建一个完整的2048游戏项目

目录 项目运行展示 项目概述 项目目标 项目结构 安装依赖 代码实现 1. 导入库 2. 创建 Game2048 类 3. 设置UI界面 4. 加载二维码图片 5. 创建菜单 6. 游戏逻辑和功能 7. 运行应用 总结 创建一个完整的2048游戏项目 项目运行展示 项目概述 在这个项目中&#xff…

常用sql:删除表中重复的数据

在平常的开发工作中&#xff0c;我们可能经常需要对表进行操作。比如某些数据重复了&#xff0c;那么可能需要删除掉重复的数据&#xff0c;保证数据根据业务字段属性相同的数据只有一条&#xff0c;那么应该如何做呢&#xff1f; 1&#xff1a;新建表&#xff1a;用户详情表 …

for循环计算1~100之间3的倍数的数字之和

你要计算1~100之间的数字先得打印出来1~100之间的数字然后在判断是不是3的倍数然后在打印出数字&#xff0c;代码如下 #include<stdio.h> int main() {int i 0;for (i 1; i < 100; i){if (i % 3 0){printf("%d ", i);}}return 0; }

Intellij IDEA多模块分组 实现move to group

新版本idea&#xff0c;没有了move to group的功能&#xff0c;导致模块很多的时候不能分组。2018版本有。 这个分组是虚拟的&#xff0c;不会在磁盘中实际存在。 要实现这个功能&#xff0c;只需要改modules.xml即可。 步骤 1. 找到配置文件 .idea目录下的moudules.xml 2.…

GeoServer GIS 服务器(geoServer离线地图服务器搭建)

文章目录 引言I GeoServer 安装部署版本选择基于war包进行部署II geoServer配置2.1 geoServer新建工作区2.2 geoServer 新建数据源2.3 geoServer图层发布和图层编辑2.4 指定存储层的坐标系2.5 geoServer图层样式2.6 图层组的创建GIS基础知识GeoServerWMTSEPSGEPSG3857相关的数据…

Cadence学习笔记(十三)--设置边框与异形铺铜

直接导入板框用小眼睛可以看到所有的都是线的属性&#xff1a; 那么如何让它变成板框呢&#xff1f;这里先跳转到下图中的层&#xff1a; 将Z--CPOY这一层变成shape区&#xff1a; 之后用Z--copy: Z--COPY设置如下参数&#xff0c;铺铜内缩20mil: 之后选择长方形铺铜就可以了&…

快醒醒,别睡了!...讲《数据分析pandas库》了—/—<5>

一、 1、修改替换变量值 本质上是如何直接指定单元格的问题&#xff0c;只要能准确定位单元地址&#xff0c;就能够做到准确替换。 1.1 对应数值的替换 具体用法如下&#xff1a; replace方法&#xff1a; df.replace(to_replace None :将被替换的原数值&#xff0c;所有…