自制小型图书管理系统 - 简单版(锻炼java基础语法的使用)

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

编程真是一件很奇妙的东西。你只是浅尝辄止,那么只会觉得枯燥乏味,像对待任务似的应付它。但你如果深入探索,就会发现其中的奇妙,了解许多所不知道的原理。知识的力量让你沉醉,甘愿深陷其中并发现宝藏。


前言

本篇通过练习小型的图书管理系统,对java基础语法的进一步应用,提高对封装、继承、抽象、接口语法的熟练度。如有错误,请在评论区指正,让我们一起交流,共同进步!


本文开始

1. 小型图书管理系统框架思想

图书管理系统:顾名思义管理书的系统,他的功能有哪些?他的使用人群是哪些?
基本功能:
① 存储书的信息:
每本书book的基础信息:书名,价格,作者等
书架(存放各种书信息的地方):BookList,可以操作书的各种信息
② 面向的使用者:user
AdminUser:管理者(管理图书)对图书的增删改等信息的操作
NormalUser:正常使用者(借阅人)对图书查找,借阅等操作
③操作:对于使用者的各种操作,单独存放,使用接口调用操作对象
④主函数Main:让使用者根据User对象,做出具体什么操作

2. 实现框架

2.1 构建书架:存放书籍

定义一个包package: book =》关于书籍的操作
Book: 存放书的各种信息(一本) - 是一个类
BookList: 多本书,使用数组存储Book[ ]

Book 代码实现:
对于书的属性实现了封装:所以需要提供get,set方法,以便于操作书里面的属性

package book;

public class Book {
    private String name;//书名
    private String author;
    private int price;
    private String  type;
    private boolean isBorrowed;//是否被借出

    //isBorrowed不需要初始化,开始的时候,书都是未被借出的默认赋值为false
    //当书真正被借出时,我们之间修改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;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                //", isBorrowed=" + isBorrowed +
                (isBorrowed ? "  已被借出 " : "  未被借出 ")+  
                //利用三木表达式判断是否借出
                '}';
    }
}

BookList 代码实现:
定义常量DEFAULT_SIZE 可以及时更改存放书的数量
书架里面封装了数组:Book[ ]可以存放多本书
usedSize: 记录书架上书的多少
【注】
这里也是封装了元素,但是出现的构造方法getBooks,setBooks不符合我们的期望,返回的是数组Book[ ], 这里只是构建框架,下面具体操作会详细说明情况!

package book;

public class BookList {
    private static final int DEFAULT_SIZE = 5;
    private Book[] books = new Book[DEFAULT_SIZE];
    private int usedSize;
   
//借书是一本本借,所以需要操作的一本书,而不是书的数组
//    public Book[] getBooks() {
//        return books;
//    }
//
//    public void setBooks(Book[] books) {
//        this.books = books;
//    }

    public int getUsedSize() {
        return usedSize;
    }

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

2.2 使用者的构建 - user

这里我们提出两种使用者:管理者和正常使用者
我们通过思考代码实践,会发现他们会有共同的属性或方法,这时可以抽象出一个类User存放他们共有的元素;
而对应管理者和正常使用者,他们的基本操作大致是一样的,只有具体的操作略有不同;

User为什么是抽象类?
主函数首先需要调用login需要显示菜单,但是父类对象没有办法使用子类里面的方法,所以menu()写成抽象方法,进而User类改成抽象类;父类再调用时发生运行时绑定,会调用子类menu()方法

User代码的实现:

package user;

import book.BookList;

public abstract class User {
    public String name;
    public User(String name) {
        this.name = name;
    }
    //主函数调用login需要显示菜单,但是父类对象没有办法使用子类里面的方法,
    // 所以menu()写成抽象方法,进而User类改成抽象类
    // 父类再调用时发生运行时绑定,会调用子类menu()方法
    public abstract int menu();
}

管理者代码实现:
知道管理者姓名,就显示可操作的菜单,根据菜单进行具体的增删改等操作

package user;
import operate.*;
import java.util.Scanner;

public class AdminUser extends User{
    //知道对象的时候,构造方法会初始化name
    public AdminUser(String name) {
        super(name);
    }

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

正常使用者代码实现

import operate.*;
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("hello  " + name + "  欢迎使用图书系统!");
        System.out.println("1.查找图书!");
        System.out.println("2.借阅图书!");
        System.out.println("3.归还图书!");
        System.out.println("0.退出系统!");
        System.out.println("========================");
        System.out.println("请输入你的操作:");
        Scanner sc = new Scanner(System.in);
        int choice = sc.nextInt();
        return choice;
    }
}

2.3 主函数构建 - Main

主函数中,使用者首先需要见到登录页面,确定登录身份输入0 或 1 确定管理者还是正常使用者,再返回对应的对象菜单;

login(): 登录操作,调用login返回对象有两种结果,所以使用(返回值类)向上转型,通过父类可以介绍多种子类对象;

import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
public class Main {
    public static User login() {//发生向上转型:返回值
        System.out.println("请输入姓名:>");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();
        System.out.println("请输入你的身份:1:管理者,0:借阅者 ");
        int choice = sc.nextInt();
        if(choice == 1) {
            return new AdminUser(name);
        } else {
            return new NormalUser(name);
        }
    }
    public static void main(String[] args) {
        BookList bookList = new BookList();
        //调用login返回的对象不确定需要父类对象来接受
        User user = login();
        //通过登录确认使用对象
        //显示登录对象的菜单,从而进行操作
        while (true) {//利用循环进行多次操作
          user.menu();//根据对象调用菜单
        }

    }
}

2.4 操作的构建 - operate

对于各种操作,都有不同的操作,我们可以定义一个接口,让所有操作implements接口,这样连接这个接口的对象都可以被同一个接口调用;

接口代码实现

package operate;
import book.BookList;
public interface IOPeration {
    void work(BookList bookList);
}

使用者的各种操作连接这个接口即可;

管理者基本操作:
查找图书:FindOperation
增加图书:AddOperation
删除图书:DelOperation
显示图书:ShowOperation
退出系统:ExitOperation

正常使用者基本操作:
查找图书:FindOperation
借阅图书:BorrowOperation
归还图书:DelOperation
退出系统:ExitOperation

2.5 对象与操作建立联系

使用者与操作建立联系:IOPeration [ ]
刚才建立了接口,可以通过接口数组存放使用者的操作对象 IOPeraton[ ]
由于都需要操作,所以接口数组,也需要定义在User中;

主函数与操作建立联系:doWork()
主函数中login()会返回对象,再根据菜单menu()返回具体选择choice,把选择与书架对象以参数形式传给doWork();

doWork()具体工作: 根据操作数组找到对象,在操作具体的工作; this.ioPerations[choice].work(bookList);
this.ioPeration[choice] => 根据选择找到操作的对象;work(bookList) => 操作对象的具体工作

更新User代码:

package user;
import book.BookList;
import operate.IOPeration;
public abstract class User {
    public String name;
    public IOPeration[] ioPerations;//操作数组存储操作对象
    public User(String name) {
        this.name = name;
    }
    public abstract int menu();
    public void doWork(int choice, BookList bookList) {
        this.ioPerations[choice].work(bookList);
        //this.ioPeration[choice] => 根据选择找到操作的对象
        //work(bookList) => 操作对象的具体工作
    }
}

main代码更新:

 public static void main(String[] args) {
        BookList bookList = new BookList();
        User user = login();
        //通过登录确认使用对象
        //显示登录对象的菜单,从而进行操作
        while (true) {//利用循环进行多次操作
            int choice =  user.menu();//根据对象调用菜单,返回操作的选择
            user.doWork(choice,bookList);
        }
    }

3. 细化各种操作内容

3.1 增加图书:AddOperation

输入图书的各种信息,再通过new对象,把书的参数给book, 再通过引用把书存放到usedSize位置,最后记录书的数量+1;
【注】通过循环查询增加的图书是否存在, 这里我们认为一本书只能存一本

增加书的代码实现:

package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class AddOperation implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("新增图书! ");
        Scanner sc = new Scanner(System.in);
        System.out.println(" 输入书名: ");
        String name = sc.nextLine();
        System.out.println(" 输入作者:");
        String author = sc.nextLine();
        System.out.println(" 输入类型:");
        String type = sc.nextLine();
        System.out.println(" 输入价格:");
        int price = sc.nextInt();
        Book book = new Book(name,author,price,type);
        int currentSize = bookList.getUsedSize();
        //判断书架上是否有此书,有就不能存入了
        for (int i = 0; i < currentSize; i++) {
            Book t = bookList.getBook(i);
            if(t.getName().equals(name)) {
                System.out.println("此书已存在,不能再放入!");
                break;
            }
        }
        //直接在最后位置存书
        bookList.setBooks(book);
        bookList.setUsedSize(currentSize+1);
        System.out.println("存入成功!");
    }
}


3.2 借阅图书:BorrowOperation

通过循环遍历,查看书是否有,状态是否是未被借出的状态;
书是对象,需要引用来获得(bookList.getBook());
因为是引用对象,比较其中的内容需要使用equals()方法;
【注】书被借出去了,记得改变书的状态

借阅图书代码实现:

package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class BorrowOperation implements IOPeration {
    @Override
    public void work(BookList bookList) {
        System.out.println("借阅图书!");
        System.out.println("请输入要借阅的图书:");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();
        int currentSize = bookList.getUsedSize();
        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            if(book.getName().equals(name) && !book.isBorrowed()) {
                book.setBorrowed(true);
                System.out.println("借阅成功!");
            }
        }
    }
}


3.3 删除图书:DelOperation

循环找到删除图书的下标,根据下标从后往前覆盖要删除的对象,使用getBook()获取删除下标的下一个位置,使用setBook()把书覆盖到前一个位置;因为是对象最后需要把最后一个位置置null;
【注】统计书架大小的需要-1;为了防止下标越界需要循环结束条件为当前书的数量-1;

删除书代码实现:

package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class DelOperation implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("删除图书!");
        System.out.println("请输入要删除图书的名字:");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();
        int currentSize = bookList.getUsedSize();
        int index = -1;
        //循环找到删除图书的下标位置
        for (int i = 0; i < currentSize; i++) {
            Book t = bookList.getBook(i);
            if(t.getName().equals(name)) {
               index = i;  //记录删除图书的位置
               break;
            }
        }
        //删除图书:都是封装的对象,需要引用变量
        for (int j = index; j < currentSize-1; j++) {
            Book book = bookList.getBook(j+1);//找到j+1下标的图书
            bookList.setBooks(j,book);//把书放到j下标位置
        }
        //修改usedSize
        bookList.setUsedSize(currentSize-1);
        //删除的是对象,最后一个位置需要置null
        bookList.setBooks(currentSize-1,null);
        System.out.println("删除成功!");
    }
}


3.4 查找图书:FindOperation

根据输入的书名,与存在的书相比较,如果有相同的即输出这本书的信息;

package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class FindOperation implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("查找图书!");
        System.out.println("请输入书名:");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();
        int currentSize = bookList.getUsedSize();
        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            if(book.getName().equals(name)) {
                System.out.println("存在这本书:");
                System.out.println(book);
                return;
            }
        }
        System.out.println("不存在这本书!");
    }
}


3.5 归还图书操作:ReturnOperation

输入归还图书的书名,比较书架上的书名与借的书名是否有相同的,并且书还是被借出去的(isBorrowed状态为ture)
【注】存在书名,归还后需要修改书的状态为false

归还书的代码操作实现:

package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class ReturnOperation implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("返回图书!");
        System.out.println("输入要归还图书的书名:");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();
        int currentSize = bookList.getUsedSize();//当前有多少图书
        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            //比较书架上的书名与借的书名是否有相同的,并且书还是被借出去的(isBorrowed状态为ture)
            if(book.getName().equals(name) && book.isBorrowed()) {
                book.setBorrowed(false);
                System.out.println("归还成功");
                return;
            }
        }
    }
}

3.6 显示存在的图书:ShowOperation

通过循环输出显示结果,不能直接使用bookList[i]打印,这是引用对象,需要打印book对象,调用会调用重写的toString()方法,显示图书信息;

显示图书代码操作:

package operate;
import book.Book;
import book.BookList;
public class ShowOperation implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("显示所有图书! ");
        int currentSize = bookList.getUsedSize();//封装的属性,只能通过对象的引用来调用
        for (int i = 0; i < currentSize; i++) {
            //System.out.println(bookList[i]);
            Book book = bookList.getBook(i);
            System.out.println(book);//通过调用重写的toString()显示书的内容
        }

    }
}

3.7 退出系统:ExitOperation

系统退出操作,输入0为一般退出操作

退出系统代码实现:

package operate;
import book.BookList;
public class ExitOperation implements IOPeration{
    @Override
    public void work(BookList bookList) {
        System.out.println("退出系统!");
        //输入0即为退出系统,系统退出的操作
        System.exit(0);
    }
}

4. 总体代码

操作代码的详细内容为上述代码细化的内容;

//关于书信息的包下内容
package book;
public class Book {
    private String name;//书名
    private String author;
    private int price;
    private String  type;
    private boolean isBorrowed;//是否被借出
    //书的元素被封装:所以需要提供构造方法,以便于操作书里面的属性
    //isBorrowed不需要初始化,开始的时候,书都是未被借出的默认赋值为false
    //当书真正被借出时,我们之间修改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;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                //", isBorrowed=" + isBorrowed +
                (isBorrowed ? "  已被借出 " : "  未被借出 ")+
                '}';
    }
}
//书架内容
package book;

public class BookList {
    private static final int DEFAULT_SIZE = 5;
    private Book[] books = new Book[DEFAULT_SIZE];
    private int usedSize;
    public BookList() {
        books[0] = new Book("三国","罗贯中",43,"小说");
        books[1] = new Book("西游记","吴承恩",40,"小说");
        books[2] = new Book("红楼梦","罗贯中",45,"小说");
        this.usedSize = 3;
    }
    public Book getBook(int pos) {
        return this.books[pos];
    }
    //AddOperation操作时直接在useSize位置添加图书
    public void setBooks(Book book) {
        this.books[usedSize] = book;
    }
    //DelOperation操作时,设置pos位置的值
    public void setBooks(int pos,Book book) {
        this.books[pos] = book;
    }
    
    public int getUsedSize() {
        return usedSize;
    }

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

//使用者包下的代码:
package user;

import book.BookList;
import operate.IOPeration;
public abstract class User {
    public String name;
    public IOPeration[] ioPerations;//操作数组存储操作对象
    public User(String name) {
        this.name = name;
    }
    //主函数调用login需要显示菜单,但是父类对象没有办法使用子类里面的方法,
    // 所以menu()写成抽象方法,进而User类改成抽象类
    // 父类再调用时发生运行时绑定,会调用子类menu()方法
    public abstract int menu();
    public void doWork(int choice, BookList bookList) {
        this.ioPerations[choice].work(bookList);
        //this.ioPeration[choice] => 根据选择找到操作的对象
        //work(bookList) => 操作对象的具体工作
    }
}

//管理者
package user;
import operate.*;
import java.util.Scanner;
public class AdminUser extends User{
    //知道对象的时候,构造方法会初始化name,初始化接口数组(管理者5个对象,借阅者4个对象)
    public AdminUser(String name) {
        super(name);
        //引用变量赋值,需要动态赋值:需要new一下;根据数组的下标调用操作对象
        this.ioPerations = new IOPeration[] {
                new ExitOperation(),
                new FindOperation(),
                new AddOperation(),
                new DelOperation(),
                new ShowOperation()
        };
    }

    @Override
    public int menu() {
        System.out.println("=======================");
        System.out.println("hello  " + 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.println("请输入你的操作:");
        Scanner sc = new Scanner(System.in);
        int choice = sc.nextInt();
        return choice;
    }
}
//普通使用者
package user;
import operate.*;
import java.util.Scanner;
public class NormalUser extends User{
    public NormalUser(String name) {
        super(name);
        this.ioPerations = new IOPeration[] {
                new ExitOperation(),
                new FindOperation(),
                new BorrowOperation(),
                new ReturnOperation()
        };
    }

    @Override
    public int menu() {
        System.out.println("=======================");
        System.out.println("hello  " + name + "  欢迎使用图书系统!");
        System.out.println("1.查找图书!");
        System.out.println("2.借阅图书!");
        System.out.println("3.归还图书!");
        System.out.println("0.退出系统!");
        System.out.println("========================");
        System.out.println("请输入你的操作:");
        Scanner sc = new Scanner(System.in);
        int choice = sc.nextInt();
        return choice;
    }
}

//主函数:
import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
public class Main {
    public static User login() {//发生向上转型:返回值
        System.out.println("请输入姓名:>");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();
        System.out.println("请输入你的身份:1:管理者,0:借阅者 ");
        int choice = sc.nextInt();
        if(choice == 1) {
            return new AdminUser(name);
        } else {
            return new NormalUser(name);
        }
    }
    public static void main(String[] args) {
        BookList bookList = new BookList();
        //调用login返回的对象不确定需要父类对象来接受
        User user = login();
        //通过登录确认使用对象
        //显示登录对象的菜单,从而进行操作
        while (true) {//利用循环进行多次操作
            int choice =  user.menu();//根据对象调用菜单,返回操作的选择
            user.doWork(choice,bookList);
        }
    }
}


总结

✨✨✨各位读友,本篇分享到内容如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值