0
点赞
收藏
分享

微信扫一扫

Java图书管理小练习(呕心沥血从0完全实现)

在当今信息化的时代,图书管理已经越来越自动化,使得图书馆和读者都更加方便了。针对这一需求,我们进行了Java图书管理小练习,学习了如何运用Java语言去实现基本的图书管理功能。

一、确定方向

首先,我给大家看一个实现完成的例子,由于导入不了视频,只能给图片了

Java图书管理小练习(呕心沥血从0完全实现)_三步走编程

这是用户登录的界面,普通的和管理员的就不一样了,下面这些选项也都是可以完成的,只不过不方便展示。

首先,我们要确定好有几个对象,然后我们再对这些对象进行更细致的实现与串联。通过上面这张图,我们至少可以确定两个对象吧,一个是区分用户的,一个是实现操作的。

但其实我们的对象是有三个:关于书的、关于用户的,还有一个是操作的(例如增加删除这些)。

二、基本框架

确定好方向之后,就可以搭建基本框架了,也就是说,方法体内部可以先不用实现(比如添加书本方法,可以先不写具体是怎么增加的),按照这种思路来写代码是很重要的,是从面向过程到面向对象的一个转型。

(1)’书‘软件包

首先,是图书信息管理模块。我们先定义一个软件包,这个包里面专门放关于书本的类,如下:

Java图书管理小练习(呕心沥血从0完全实现)_面向对象_02

包名一定要小写,这是一种编码规范。

在这个书的软件包里面,有什么是关于书的呢?首先,这里面肯定要有个书的类,这是毋庸置疑的,那还有呢?我们放书,是不是还需要有书架呀,所以我们可以定义两个类,其中一个类我们就叫Book,里面包括书籍名称、作者、价格、类型等属性。代码如下:

package book;
public class Book {
    private String name;//书名
    private String author;//作者
    private double price;//价格
    private String type;//类型
    private boolean isBorrowed;//是否被借出
    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 double getPrice() {
        return price;
    }
    public void setPrice(double 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;
    }
}

注:这里我建议用private来修饰,需要改动的话就用getset修改,提高代码安全性和可读性。

另外一个类,我们就叫BookList,书架上的书籍我们就用数组给它串起来(主要是我们存多种类型相同的数据只学过数组,后面用链表啊这些就会简单很多)代码如下:

package book;
public class BookList {
    private Book[] books = new Book[10];//设置一个Book类型的数组,不初始化,因为不知道要放几本书
    private int bookSize;//放的实际的书本数
    public BookList() {
        
    }
}

有很多小伙伴会想了,那我要把我的书传给Book啊(比如姓名,作者这些东西),不然怎么初始化呢?唉,说的很对,所以我们要在Book里面把构造方法给补上,Book构造方法如下:

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

所以,这更加说明了,我们写代码只是先想好一个思路,至于实现,那是一个字一个字敲出来的,需要增删查改的地方我们再写,总之就是边写边看,最重要的是先动手。

那我们BoolList就可以这样写了:

package book;

public class BookList {
    private Book[] books = new Book[10];
    private int bookSize;
    public BookList() {
        books[0] = new Book("樱花庄的宠物女孩", "鸭志田一", 29.9, "轻小说");
        books[1] = new Book("约会大作战", "橘公司&Tsunako", 69.9, "轻小说");
        books[2] = new Book("龙王的牢饭", "白鸟士郎", 29.9, "轻小说");
        bookSize = 3;
    }
}

(不好意思,这里都是博主比较喜欢的日本小说)Java图书管理小练习(呕心沥血从0完全实现)_面向对象_03

(2)‘用户’软件包

写完这些,关于书的框架就基本上搭好了,然后是关于用户的,和上面的书的包一样,先定义一个user的包,如下:

Java图书管理小练习(呕心沥血从0完全实现)_三步走编程_04

这个软件包呢我们就存放两个类,一个是关于用户的,一个是关于管理员的,那定义好这两个类之后,我们第一步,是不是要写个菜单方法呢?我们这个方法就叫menu吧,我们只需把一开始的那张图上显示出来的东西打印出来就好了,但是有一个问题,就是那里面的名字,他怎么知道我就叫稚名不带撇呢?就算是我输入的,那该怎么写呢?不能在用户的这个类里面写哦,因为我是先输入名字,再输入身份的,你没确定我的身份之前,怎么知道要调用的是管理员,还是普通用户呢?

所以我们可以在软件包的外面定义一个Main方法体,这里面就是专门干这些东西的,并且,我们要写一个用户的抽象类User,这个类我们就写一个菜单方法和构造函数来接收我们的nameMain的外面写一个方法login,返回值就是User,结合向下转型,你能想到什么?没错,就是返回的是哪个子类的类型,我们就调用哪个的菜单,理论结束,下面是Main的代码实现:

import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;

public class Main {
    public static User login() {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你的姓名->");
        String name = sc.nextLine();
        System.out.print("1:管理员  0:普通用户" + "\n" + "请输入你的身份->");
        int ues = sc.nextInt();
        if (ues == 1) {
            return new AdminUser(name);//将返回的类型强转为User
        }
        else {
            return new NormalUser(name);
        }
    }
    public static void main(String[] args) {
        User user = login();
        user.menu();//返回什么类型,就调用什么类型的menu
    }
}

然后是用户的抽象类、管理员和普通用户的:

//User
package user;
abstract public class User {
    public String name;
    abstract public void menu();

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

//管理员的
package user;
public class AdminUser extends User{
    public AdminUser(String name) {
        super(name);
    }
    @Override
    public void menu() {
        System.out.println("管理员菜单");
        System.out.println("=====================");
        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("=====================");
    }
}

//普通用户
package user;
import java.util.Scanner;
public class NormalUser extends User{
    public NormalUser(String name) {
        super(name);
    }
    @Override
    public void menu() {
        System.out.println("管理员菜单");
        System.out.println("=====================");
        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("=====================");
    }
}

定义好这些之后,我们的用户大致框架也差不多搭建好了,就可以爽一下了,结果如下:

Java图书管理小练习(呕心沥血从0完全实现)_三步走编程_05

接下来就是那些查找书籍这写操作实现了

(3)‘操作’软件包

老样子,我们还是定义一个包,包的名字我们就叫operation吧,统计一下需要实现的操作<查找图书;新增图书;删除图示;显示图书;借阅图书;归还图书;退出程序>,还需要定义一个接口,里面放一个实现的方法,,后面的操作全部引用这个接口,定义一个叫shiXian的方法,形参先放着不写,用来他的子类写实现这些具体操作的内部代码的,这样子就不会忘记哪个操作没有实现方法了,所以我们就得到以下的包:

Java图书管理小练习(呕心沥血从0完全实现)_普通用户_06

下面这是IOperation接口的代码:

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

三、串联对象小技巧

(4)对象的连接

那我们,到底要怎么把这些包给连起来呢???Java图书管理小练习(呕心沥血从0完全实现)_普通用户_07

这是个很严重的问题,好兄弟们,我们可以在User定义一个方法,这个方法连接我们的操作包,连接上,就好办了嘛,所以我们要定义一个BookList类型的数据传过去,把书架传过去,才好对书籍进行增删查改,还有,我们不是要选择执行第几个操作么,所以我们选择的数字也要返回来,和BookList类型一起传过去,我们的代码就变成这样了:

//Main
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
public class Main {
    public static User login() {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你的姓名->");
        String name = sc.nextLine();
        System.out.print("1:管理员  0:普通用户" + "\n" + "请输入你的身份->");
        int ues = sc.nextInt();
        if (ues == 1) {
            return new AdminUser(name);//将返回的类型强转为User
        }
        else {
            return new NormalUser(name);
        }
    }
    public static void main(String[] args) {
        User user = login();
        int choice = user.menu();//返回什么类型,就调用什么类型的menu
    }
}

//用户父类

package user;
abstract public class User {
    public String name;
    abstract public int menu();

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

//管理员用户类

//普通用户类

package user;
import java.util.Scanner;
public class NormalUser extends User{
    public NormalUser(String name) {
        super(name);
    }
    @Override
    public int menu() {
        System.out.println("管理员菜单");
        System.out.println("=====================");
        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("=====================");
        System.out.print("请输入->");
        Scanner sc = new Scanner(System.in);
        return sc.nextInt();
    }
}

那我们的这些选择的操作该怎么办呢?,就算返回了,我们的操作该怎么访问到呢?怎么样才能调用这些操作呢?

我知道你很急,但你先别急,我们可以定义一个IOperation类型的数组,然后这个数组去new该用户所拥有的对象方法,等会传过来的choice就直接是这个数组的下标,直接就能引用了,如下:

//管理员用户类

package user;
import operation.*;
import java.util.Scanner;
public class AdminUser extends User{
    public AdminUser(String name) {
        super(name);
        this.iOperation = new IOperation[] {
                new ExitOperation(),
                new FindOperation(),
                new AddOperaiton(),
                new DelOperation(),
                new ShowOperation()
        };
    }
    @Override
    public int menu() {
        System.out.println("管理员菜单");
        System.out.println("=====================");
        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("=====================");
        System.out.print("请输入->");
        Scanner sc = new Scanner(System.in);
        return sc.nextInt();
    }
}

//普通用户

package user;
import operation.*;
import java.util.Scanner;
public class NormalUser extends User{
    public NormalUser(String name) {
        super(name);
        this.iOperation = new IOperation[] {
                new ExitOperation(),
                new FindOperation(),
                new BorrowOperation(),
                new ReturnOperation()
        };
    }
    @Override
    public int menu() {
        System.out.println("管理员菜单");
        System.out.println("=====================");
        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("=====================");
        System.out.print("请输入->");
        Scanner sc = new Scanner(System.in);
        return sc.nextInt();
    }
}

做完这些工作之后,还记得我说的什么吗?那就是需要把这三个给串起来,把你的选选择和这本创建好的书给User传过去,这个方法的名称是shiXian,所以它的形参又得改了,如下:

public interface IOperation {
    void shiXian(int i, BookList bookList);
}

所以又验证了博主的那句话:”边写边看。“

于是Main类和User类的代码就变成了这样->

//Main类

import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
public class Main {
    public static User login() {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你的姓名->");
        String name = sc.nextLine();
        System.out.print("1:管理员  0:普通用户" + "\n" + "请输入你的身份->");
        int ues = sc.nextInt();
        if (ues == 1) {
            return new AdminUser(name);//将返回的类型强转为User
        }
        else {
            return new NormalUser(name);
        }
    }
    public static void main(String[] args) {
        User user = login();
        int choice = user.menu();//返回什么类型,就调用什么类型的menu
        BookList bookList = new BookList();
        user.chuanLian(choice, bookList);
    }
}

//User类

package user;
import book.BookList;
import operation.IOperation;
abstract public class User {
    public String name;
    abstract public int menu();
    IOperation[] iOperation;
    public User(String name) {
        this.name = name;
    }
    public void chuanLian(int i, BookList bookList) {
        //谁调用这个函数,就调用谁的接口数组i是表示这是数组里面的第几个元素,也就是new哪个方法,
        //每个操作方法里面都有实现这个方法,把书架传过去,才能操作这些书
        this.iOperation[i].shiXian(bookList);
    }
}


其实写到这儿,你已经可以爽一下了,就是这个shiXian方法里面,随便写点,比如我这样

Java图书管理小练习(呕心沥血从0完全实现)_User_08

感觉自己是写了,其实啥都没写Java图书管理小练习(呕心沥血从0完全实现)_System_09,好了,玩笑到此为止。

四、操作具体内部实现

(1)退出程序代码实现

首先,我们先挑软柿子捏,直接写退出程序这个方法,很简单,如下;

package operation;
import book.BookList;
public class ExitOperation implements IOperation{
    @Override
    public void shiXian(BookList bookList) {
        System.out.println("退出程序!");
        System.exit(0);
    }
}

你甚至还可以不要打印,就一行代码,然后我们再挑软一点的,显示图书,这个就要使用到我们的get、set、toString方法了,下面是代码实现:

(2)显示所有书籍代码实现

//书架类

package book;
public class BookList {
    private Book[] books = new Book[10];
    private int bookSize;
    public BookList() {
        books[0] = new Book("樱花庄的宠物女孩", "鸭志田一", 29.9, "轻小说");
        books[1] = new Book("约会大作战", "橘公司&Tsunako", 69.9, "轻小说");
        books[2] = new Book("龙王的牢饭", "白鸟士郎", 29.9, "轻小说");
        bookSize = 3;
    }
    public int getBookSize() {
        return bookSize;
    }
    public void setBookSize(int bookSize) {
        this.bookSize = bookSize;
    }
    public Book getBooks(int i) {
        return books[i];
    }
    public void setBooks(Book[] books) {
        this.books = books;
    }
}

//书类

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

Book这个类要在原有基础上再加上一个toString方法

//显示所有书籍

package operation;
import book.Book;
import book.BookList;
public class ShowOperation implements IOperation{
    @Override
    public void shiXian(BookList bookList) {
        int count = bookList.getBookSize();
        for (int i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            System.out.println(book);
        }
    }
}

(3)查找书籍代码实现

会显示所有书籍的话,那查找书籍就好做了,加个if判断条件就行了,下面是代码实现:

package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class FindOperation implements IOperation{
    @Override
    public void shiXian(BookList bookList) {
        System.out.println("查找图书!");
        int count = bookList.getBookSize();
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你需要查找的书籍->");
        String name = sc.nextLine();
        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("未找到");//到了这儿,就是for寻找完了,所以没找到
    }
}

(4)借/还 书代码实现

然后是借书和还书,修改它们的isBorrowed就可以了,下面是代码实现:

//借书
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class BorrowOperation implements IOperation{
    @Override
    public void shiXian(BookList bookList) {
        int count = bookList.getBookSize();
        for (int i = 0; i < count; i++) {
            System.out.println(bookList.getBooks(i));
        }
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你需要借的书->");
        String name = sc.nextLine();
        for (int i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            if (book.getName().equals(name)) {
                book.setBorrowed(true);
            }
        }
    }
}

//还书
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class ReturnOperation implements IOperation{
    @Override
    public void shiXian(BookList bookList) {
        int count = bookList.getBookSize();
        for (int i = 0; i < count; i++) {
            System.out.println(bookList.getBooks(i));
        }
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你需要借的书->");
        String name = sc.nextLine();
        for (int i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            if (book.getName().equals(name)) {
                book.setBorrowed(false);
            }
        }
    }
}

(5)添加书籍代码实现

然后我们下一步是要进行,这个要比较难亿点,你需要传两个东西给书架,一个是书本的参数,一个是最后一个书本的下标,所有就需要改动编译器给你自动重写的setBooks方法了,下面是代码实现:

//setBooks要改成这样

public void setBooks(int i, Book books) {
        this.books[i] = books;
    }

//添加书籍

package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class AddOperaiton implements IOperation{
    @Override
    public void shiXian(BookList bookList) {
        int count = bookList.getBookSize();
        Scanner sc = new Scanner(System.in);
        System.out.print("书名->");
        String name = sc.nextLine();
        System.out.print("作者->");
        String author = sc.nextLine();//作者
        System.out.print("类型->");
        String type = sc.nextLine();//类型
        System.out.print("价格->");
        double price = sc.nextDouble();//价格
        Book book = new Book(name,author,price,type);//传给书,让他再初始化一本,然后传给Book这个结构体
        bookList.setBooks(bookList.getBookSize(), book);//更改Book
        bookList.setBookSize(bookList.getBookSize() + 1);//再传给setSize让他+1
    }
}

(6)删除书籍代码实现

删除书籍和添加书籍差不多,可以用迭代覆盖想法,就是先找到想删的这本书,然后一直把他的后一本覆盖掉他的前一本,最后size--,下面是代码实现

package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class DelOperation implements IOperation{
    @Override
    public void shiXian(BookList bookList) {
        int count = bookList.getBookSize();
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你需要删除的书籍->");
        String name = sc.nextLine();
        int i = 0;
        for (i = 0; i < count; i++) {
            Book book = bookList.getBooks(i);
            if (book.getName().equals(name)) {
                break;
            }
        }
        if (i >= bookList.getBookSize()) {
            System.out.println("未找到要删除的书籍!");
            return;
        }
        else {
            //利用for循环,i是那本书的位置,把i+1的书给i这里,迭代往后走
            for (int j = i + 1; j < bookList.getBookSize(); j++) {
                Book book = bookList.getBooks((j));
                bookList.setBooks(i,book);
                i++;
            }
            bookList.setBookSize(bookList.getBookSize() - 1);
            System.out.println("删除成功!");
        }
    }
}

写到这儿就算完成了,不过还有点瑕疵,就是不能循环使用,每次都要重写开始太麻烦了,所以我们可以用死循环控制,直到选择0强行退出,改一点点代码就可以了,如下:

public static void main(String[] args) {
        User user = login();
        BookList bookList = new BookList();
        while (true){
            int choice = user.menu();//返回什么类型,就调用什么类型的menu
            user.chuanLian(choice, bookList);
        }
    }

main函数中把这两行输入给死循环就ok了。感谢大家能看到这里,今天的心灵鸡汤肯定也少不了咯Java图书管理小练习(呕心沥血从0完全实现)_普通用户_10

五、心灵鸡汤

Java是一门不断发展和变革的编程语言。在学习和掌握它的过程中,我们需要不断拥抱新技术、保持创新和进步的决心。无论是开发桌面应用程序、企业级应用、Web应用还是移动端应用,Java都能为我们提供强大的支持和优秀的应用体验。对于Java程序员而言,挑战和机遇始终存在。让我们继续保持孜孜不倦的追求,不忘初心,砥砺前行,秉承着 "Write Once, Run Anywhere" 的原则,为塑造更美好的IT世界而努力奋斗。

Java图书管理小练习(呕心沥血从0完全实现)_面向对象_11

Java图书管理小练习(呕心沥血从0完全实现)_System_12

举报

相关推荐

0 条评论