【Java】面向对象思想——简易实现图书管理系统(详解)

文章目录

  • 前言
  • 一、实现思路
    • 1.自定义类
    • 2.自定义接口
  • 二、代码解析
    • book 包
      • Book 类
      • BookShelf类
    • user 包
      • User 父类
      • Administrator 子类
      • Customer 子类
    • operate 包
      • Operate 接口
      • Add 类
      • Delete 类
      • Show 类
      • Find 类
      • Borrow 类
      • Return 类
      • Exit 类
    • Test类
      • 补充 User 父类
      • 补充 Administrator 子类
      • 补充 Customer 子类
    • 完整 Show 类
        • 补充 BookShelf 类
    • 完整 Add 类
    • 完整 Delete 类
    • 完整 Find 类
    • 完整 Exit 类
    • 完整 Borrow 类
    • 完整 Retrun 类
  • 三、源码
  • 总结


前言

各位读者好, 我是小陈, 这是我的个人主页
小陈还在持续努力学习编程, 努力通过博客输出所学知识
如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽
希望我的专栏能够帮助到你:
JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)

前几篇文章介绍了:
1️⃣Java的【类和对象】
2️⃣面向对象的三大特征【封装】,【继承】,【多态】
3️⃣Java的【接口】

本篇将结合之前所讲的【面向对象】知识,实现一个简易版的 “图书管理系统” ,来加强巩固这一部分相关知识的掌握

具体的代码实现可能和小伙伴们认为的逻辑不同噢,毕竟条条大路通罗马~


提示1:本篇是非常非常基础且简易粗糙的小练习,如有大佬已经掌握了高级的实现方式,请请轻喷!!也欢迎小伙伴们评论区讨论~

提示2:本篇只实现主要的功能,很多细节可能不会完美的处理,如果小伙伴们发现一些影响不大的bug请勿喷,完善bug不是本篇的主要目标

一、实现思路

在【类和对象】文章中说过,在Java的世界里一切皆对象
所以要想学好面向对象语言,首先需要有把事物抽象出来的能力
对于图书管理系统而言,对象都有哪些呢?

1️⃣简单来说可以分为:
2️⃣并且系统中又存放着很多本书,所以应该用数组来存放书,所以还应该有一个书架

本篇以简易练习为主,所以只设置1️⃣个书架,书架上只存本书

暂时确定好了 人,书,书架 这3️⃣个对象之后,问题又来了:
我们应该如何自定义一个类,来描述这个对象呢?

这就要思考这三个类分别需要什么成员属性成员方法


1.自定义类

暂时我们需要定义的类有:Book,BookShelf,User

目前,Book类 需要有:
成员属性“bookName”,“author”,“price”,“isBorrowed”
构造方法:初始化 Book

❗️❗️❗️为了体现【封装】特性,把这些成员属性用 private 修饰❗️❗️❗️
下面其他类中的成员属性同理

成员方法gettersetter (体现封装)


目前, BookShelf 类 需要有:
成员属性“Book[ ] books” ( Book 类型的数组), “size”(书架上存放书的实际个数)

类就是一种类型,我们定义了一个 Book 类之后,Book 就是一个变量的类型✅
例如:定义一个存放 整形 的数组 : int[ ] + 变量名
所以定义一个存放 Book 的数组 :Book[ ] + 变量名

构造方法:初始化 BookShelf (为了方便,默认存放3️⃣本书)
成员方法gettersetter


❓❓❓在定义 User 这个类之前,需要思考为什么要有 “人” 这个对象

图书管理系统需要 “人” 来操作,那么 “人” 的身份又分为两种:“管理员”,**“用户”**身份,操作的选项也不同:

“管理员” 需要的操作:显示图书信息、增加图书信息、删除图书信息、查询图书信息、退出系统
“用户” 需要的操作:查询图书信息、借阅图书、归还图书、退出系统

⚠️⚠️⚠️我们希望:
在登录时,让使用者输入姓名,并选择身份,根据身份的不同,提供不同的操作选项这不就是 多态 的思想吗✅

所以我们还需定义 “Administrator”“Customer” 两个子类,来继承 User 这个父类(继承是多态的前提)

这样就可以在 “Administrator”“Customer” 两个子类中分别定义 menu 成员方法,来打印对应的操作菜单

目前, User 类 需要有:
成员属性“name” 即可
构造方法:初始化 name
成员方法menu,子类用来打印操作菜单,所以 User 作为父类,只需要用 abstract 修饰即可

“Administrator”“Customer” 两个子类中,需要提供
构造方法:帮助父类初始化 name
分别提供成员方法menu


2.自定义接口

上面说到,不同的身份会对应不同的操作菜单,根据这两份操作菜单中的操作选项就可以抽象出一个接口: Operate

而接口不能单独使用,必须被 “类” 实现,所以我们就可以把:

“管理员” 需要的操作:显示图书信息、增加图书信息、删除图书信息、查询图书信息、退出系统
“用户” 需要的操作:查询图书信息、借阅图书、归还图书、退出系统

这些操作,分别定义成 :
“Add” 增加
“Delete” 删除
“Show” 显示
“Find” 查找
“Borrow” 借阅
“Return” 归还
“Exit” 退出

让这些 都 实现 Operate这个接口,在 Operate 接口中 定义一个抽象方法: operate(),这样就只需要在这些 重写 operate() 方法即可✅


大概的框架我们已经分析过了,下面我们一点点解析代码

二、代码解析

首先我们把刚刚分析的大致框架写出来:


book 包

我们新建一个 book 包,包中新建 Book 类和 BookShelf 类:

Book 类

public class Book {
    private String bookName;
    private String author;
    private double price;
    private boolean isBorrowed;

    // 构造方法
    public Book(String bookName, String author, double price) {
        this.bookName = bookName;
        this.author = author;
        this.price = price;
    }
    
    // getter 和 setter
    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

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

    public void setIsBorrowed(boolean isBorrowed) {
        this.isBorrowed = isBorrowed;
    }
}

可以看到构方法中没有 isBorrowed 这个参数,是因为 boolean 类型的变量即使不初始化,系统也会赋给一个默认值,默认为 “false”

BookShelf类

public class BookShelf {
    private Book[] books = new Book[10];
    private int size;

    // 构造方法
    public BookShelf() {
        books[0] = new Book("瓦尔登湖", "张三", 39.9);
        books[1] = new Book("百年孤独", "李四", 49.9);
        books[2] = new Book("赎罪", "王五", 38.8);
        this.size = 3;
    }

    //getter 和 setter
    public Book[] getBooks() {
        return books;
    }

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

    public int getSize() {
        return size;
    }
    
    public void setSize(int size) {
        this.size = size;
    }
}

在构造方法中默认存放3️⃣本书即可
注意: getBooks 方法的返回值是 Book[ ] ,也就是说我们得到的是 存放书的整个数组


user 包

我们接下来再新建一个 user 包,在 user 包中新建一个父类 User ,再新建两个子类 “Administrator”“Customer” ,分别继承 User 父类

User 父类

public abstract class User {
    protected String name;

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

    // 抽象方法,在子类中分别实现
    public abstract void menu();
}

Administrator 子类

public class Administrator extends User {
    // 构造方法
    public Administrator(String name) {
        super(name);
    }

    public void menu() {
        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("——————————————");
    }
}

Customer 子类

public class Customer extends User{
    // 构造方法
    public Customer(String name) {
        super(name);
    }
    
    public void menu() {
        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("——————————————");
    }
}

operate 包

我们接下来再新建一个 operate 包,在 operate 包中新建一个接口 Operate ,再新建所需操作对应的类 :
“Add” 增加
“Delete” 删除
“Show” 显示
“Find” 查找
“Borrow” 借阅
“Return” 归还
“Exit” 退出

Operate 接口

public interface Operate {
	// 抽象方法
    void operate(BookShelf bookShelf);
}

重要的事说第二遍!
Operate 接口中的抽象方法不需要具体实现,因为下面的类都 implements 了 Operate 接口,所以只需要在各自类中 重写 即可

下面暂时不重写 operate 方法,先写大致框架

Add 类

public class Add implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
    }
}

Delete 类

public class Delete implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
    }
}

Show 类

public class Show implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
    }
}

Find 类

public class Find implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
    }
}

Borrow 类

public class Borrow implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
    }
}

Return 类

public class Return implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
    }
}

Exit 类

public class Exit implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
    }
}

Test类

上面都写完之后,在 scr 包或者 user 包下面新建一个 Test 类,用来写 main 方法及其他相关代码
(博主是在 src 下面新建 Test 类)

从 Test 类开始解析 ~~ !!

我们希望在程序运行起来后,让使用者输入姓名,选择(输入)身份,根据身份不同,给使用者显示不同的菜单 (多态思想),让使用者输入操作选项,根据选择,执行对应的程序( operate 方法)(接口操作)

可以总结为三部分:
1️⃣输入姓名,选择身份 (登录)
2️⃣打印菜单
3️⃣选择操作

第1️⃣部分:登录

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

        System.out.println("请选择你的身份: 1->管理员  2->顾客");
        Scanner sc = new Scanner(System.in);
        int idOption = scanner.nextInt();
        
        if(idOption == 1) {
            return new Administrator(name);
        }else {
            return new Customer(name);
        }
    }
    
    public static void main(String[] args) {
        // 向上转型
        User user = login();
    }

根据 idOption 的不同,返回值处 new 对应的身份的对象,在 main() 方法中用User 父类接收子类,实现向上转型,实际上是为了接下来的多态做准备️

第2️⃣部分:打印菜单

    ....
    public static int printMenu(User user) {
        user.menu();  // 实现多态
        System.out.println("请选择你的操作:");
        Scanner scanner = new Scanner(System.in);
        return scanner.nextInt();
    }
    
    public static void main(String[] args) {
        // 向上转型
        User user = login();
        // 打印菜单 
        printMenu(user);
    }

在 printMenu() 方法中第一行就实现了多态,执行子类对象的 menu() 方法 ,发生了动态绑定
最后根据菜单提示,输入对应操作的序号,作为返回值✅

这里在 main 方法中暂时没有接收返回值,是为了抛出一个疑问:
我们需要接收返回值吗,要返回值有什么用?

废话!!当然需要返回值,没有返回值,我咋知道你选择的哪个序号,我咋给你执行对应的 operate() 方法???

好, 问题就出现在这❗️❗️❗️本篇最最最最关键点来了❗️❗️❗️

我们需要根据返回值 (数字序号) ,来执行对应的 operate() 方法
像不像根据下标(数字序号)访问数组?而 接口也是一种引用数据类型

所以我们可以定义一个接口类型的数组❗️❗️❗️,数组中按需求存放 “Add”“Delete”“Show”“Find”“Borrow”“Return”“Exit”

【Java】面向对象思想——简易实现图书管理系统(详解)_第1张图片

所以我们在 User 父类中:
1️⃣补充一个成员属性:Operate 数组,只声明即可,在子类中利用构造方法帮助父类进行初始化这个数组(如图),因为 Operate 数组中的元素都是引用数据类型,所以初始化数组的过程就是实例化对象(图中没有写 new 关键字)
2️⃣补充一个成员方法:doOperate() ,如图中最后一行所示,利用下标访问对应的类中的 operate 方法

补充 User 父类

public abstract class User {
    protected String name;
    protected Operate[] operates; //数组,存放不同的操作(对象)

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

    public abstract void menu();

    // 重点!
    public void doOperate(int operateOption, BookShelf bookShelf) {
        this.operates[operateOption].operate(bookShelf);
    }
}

补充了一个成员属性和成员方法

在 doOperate() 方法中,我们操作的对象是存放书的数组(书架),所以将定义的 bookshelf 作为参数传递

补充 Administrator 子类

public class Administrator extends User {
    // 构造方法
    public Administrator(String name) {
        super(name);
        this.operates = new Operate[]{
                new Exit(),
                new Show(),
                new Add(),
                new Delete(),
                new Find()
        };
    }

    public void menu() {
        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("——————————————");
    }
}

根据菜单补充了构造方法,初始化Operate数组

补充 Customer 子类

public class Customer extends User{
    // 构造方法
    public Customer(String name) {
        super(name);
        this.operates = new Operate[]{
                new Exit(),
                new Find(),
                new Borrow(),
                new Return(),
        };
    }
    public void menu() {
        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("——————————————");
    }
}

根据菜单补充了构造方法,初始化Operate数组


BB那么多,到现在 main 方法中的第3️⃣部分:执行操作就很简单了:

定义一个 operateOption(操作选项)变量 接收 printMenu() 方法的返回值
再调用 user 对象中的 doOperate() 方法即可
当然需要将 操作选项书架 作为参数传递

最后记得加上 while 循环噢

    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf();

        // 向上转型
        User user = login();

        while(true) {
            // 打印菜单 选择操作 【多态】
            int operateOption = printMenu(user);
            //执行操作
            user.doOperate(operateOption, bookShelf);
        }
    }

至此,我们的 user 包和 Test 类就全部写完了
完整的 Test 类

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

        System.out.println("请选择你的身份: 1->管理员  2->顾客");
        Scanner sc = new Scanner(System.in);
        int idOption = scanner.nextInt();
        if(idOption == 1) {
            return new Administrator(name);
        }else {
            return new Customer(name);
        }
    }

    public static int printMenu(User user){
        user.menu();
        System.out.println("请选择你的操作:");
        Scanner scanner = new Scanner(System.in);
        return scanner.nextInt();
    }

    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf();
        
        // 登录 接收返回值时发生向上转型
        User user = login();

        while(true) {
            // 打印菜单 选择操作 【多态】
            int operateOption = printMenu(user);

            //执行操作
            user.doOperate(operateOption, bookShelf);
        }
    }
}

接下来就只剩下 operate 包中的几个 表示操作” 的

完整 Show 类

public class Show implements Operate {

    @Override
    public void operate(BookShelf bookShelf) {
        System.out.println("图书信息如下:");
        bookShelf.printBookShelf(bookShelf);
    }
}

原本应该在 Show 这个类中遍历书架并打印相关信息,但后续会多次需要遍历并打印

所以为了避免代码冗余❎,把 printBookShelf() 单独写成一个方法✅,在 BookShelf 类中实现(同时和 Test 类中的 printMenu() 方法对应)

⚠️没有必要写成 Static 静态方法,因为我们在main方法中一定会实例化bookShelf对象,所以通过对象访问 printBookShelf() 也完全可行

补充 BookShelf 类

    public void printBookShelf(BookShelf bookShelf) {
        int size = bookShelf.getSize();
        for (int i = 0; i < size; i++) {
            System.out.print(i + 1 + ": ");
            System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + "  "
                    + "作者: " + bookShelf.getBooks()[i].getAuthor() + "  "
                    + "价格:"+ bookShelf.getBooks()[i].getPrice() + "元  "
                    + (bookShelf.getBooks()[i].getIsBorrowed()?"   已背借出":"   未被借出"));
        }
    }

这里最后一行,打印 isBorrowed 的值时还用到了一个三目运算符 再打打基础哈哈哈哈哈


完整 Add 类

public class Add implements Operate {
    @Override
    // 重写 Operate 接口中的 operate 方法
    public void operate(BookShelf bookShelf) {
        System.out.println("请依次输入:书名、作者、价格");

        Scanner scanner1 = new Scanner(System.in);
        String newBookName = scanner1.nextLine();
        Scanner scanner2 = new Scanner(System.in);
        String newAuthor = scanner2.nextLine();
        Scanner scanner3 = new Scanner(System.in);
        double newPrice = scanner3.nextDouble();

        int size = bookShelf.getSize();
        bookShelf.getBooks()[size] = new Book(newBookName, newAuthor, newPrice);
        System.out.println("增加成功\n");
        bookShelf.setSize(++size);
    }
}

这里我们默认 添加的图书位置在最后一位

分为四步:
1️⃣从控制台输入相关信息( isBorrowed 不用输入,默认是 false )
2️⃣new 一个 Book 类的对象,利用构造方法初始化图书信息
3️⃣将 new 的新对象的引用赋给 bookShelf.getBooks()[size]

bookShelf.getBooks() 这个方法的返回值是Book[ ],是一个数组,所以后面通过 “[ ]” 操作符就可以访问数组内的元素,size 下标就是最后一个元素

4️⃣通过 setter 方法把被封装的 size 加1


完整 Delete 类

public class Delete implements Operate {
    @Override
    // 重写 Operate 接口中的 operate 方法
    public void operate(BookShelf bookShelf) {
        int size = bookShelf.getSize();
        bookShelf.printBookShelf(bookShelf);

        System.out.print("请输入您要删除第几本书:");
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();

        for (int i = num - 1; i < size - 1; i++) {
            bookShelf.getBooks()[i] = bookShelf.getBooks()[i + 1];
        }
        bookShelf.setSize(--size);
        System.out.println("删除成功\n");

        bookShelf.printBookShelf(bookShelf);
    }
}

这里删除某一个位置的图书,利用的思想是将后一个位置的图书信息覆盖到前一个位置上,注意 顺序从前往后

注意:
for 循环的判断条件是 i < size - 1 ,不能是 <=
因为:此时的书架只放了 3️⃣本书,如果❗️❗️书架上放满了书,size 为❗️❗️, bookShelf.getBooks()[i] = bookShelf.getBooks()[i + 1];
访问 i + 1 下标时就会数组越界❌


完整 Find 类

public class Find implements Operate {
    @Override
    // 重写 Operate 接口中的 operate 方法
    public void operate(BookShelf bookShelf) {
        System.out.println("请输入你要查询的书名");
        Scanner scanner = new Scanner(System.in);
        String targetName = scanner.nextLine();

        int size = bookShelf.getSize();
        for (int i = 0; i < size; i++) {
            if(bookShelf.getBooks()[i].getBookName().equals(targetName)) {
                System.out.println("该书籍信息如下:");
                System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + "  "
                        + "作者: " + bookShelf.getBooks()[i].getAuthor() + " "
                        + "价格: "+ bookShelf.getBooks()[i].getPrice() + "元 "
                        + "是否被借出: " + bookShelf.getBooks()[i].getIsBorrowed());
                return;
            }
        }
        System.out.println("未查询到此书\n");
    }
}

这个很好理解,不多赘述

bookShelf.getBooks()[i].getBookName() 这行代码乍一看很长实际上也很好理解:
1️⃣首先 bookShelf.getBooks() 通过对象访问得到书架这个成员属性(得到数组)
2️⃣再通过下标 i 访问到具体的那本书
3️⃣再通过 “点号” 访问这个 Book 对象的getBookName() 成员方法


完整 Exit 类

public class Exit implements Operate {
    @Override
    // 重写 Operate 接口中的 operate 方法
    public void operate(BookShelf bookShelf) {
        System.out.println("感谢使用本系统,再见!");
        System.exit(0);
    }
}

这里只需要用到一个 System.exit(0) 库方法即可,程序正常结束时就会在控制台输出 “Process finished with exit code 0” 不过多做研究 ~


完整 Borrow 类

public class Borrow implements Operate {
    @Override
    // 重写 Operate 接口中的 operate 方法
    public void operate(BookShelf bookShelf) {
        System.out.println("请输入您要借阅的书名");
        Scanner scanner = new Scanner(System.in);
        String borrowName = scanner.nextLine();

        int size = bookShelf.getSize();

        for (int i = 0; i < size; i++) {
            if (bookShelf.getBooks()[i].getBookName().equals(borrowName)) {
                if(bookShelf.getBooks()[i].getIsBorrowed()) {
//                if (bookShelf.getBooks()[i].getIsBorrowed() == false) {
                    System.out.println("抱歉,该书已被借出\n");
                    return;
                }else {
                    bookShelf.getBooks()[i].setIsBorrowed(true);
                    System.out.println("借阅成功\n");
                    return;
                }
            }
        }
        System.out.println("操作失败,本系统内不存在此书");
    }
}

这里也仅仅是一些简单的逻辑判断

注意:if( bookShelf.getBooks()[i].getIsBorrowed() ) { 这行代码
if 判断语句的括号内规定是布尔表达式,而我们 getIsBorrowed() 方法的返回值正是 true 或 false ,利用逻辑判断即可简化代码


完整 Retrun 类

public class Return implements Operate {
    @Override
    // 重写 Operate 接口中的 operate 方法
    public void operate(BookShelf bookShelf) {
        System.out.println("请输入您要归还的书名");
        Scanner scanner = new Scanner(System.in);
        String borrowedName = scanner.nextLine();

        int size = bookShelf.getSize();

        for (int i = 0; i < size; i++) {
            if(bookShelf.getBooks()[i].getBookName().equals(borrowedName)) {
                if(bookShelf.getBooks()[i].getIsBorrowed()) {
//                if(bookShelf.getBooks()[i].getIsBorrowed() == true) {
                    bookShelf.getBooks()[i].setIsBorrowed(false);
                    System.out.println("归还成功\n");
                    return;
                }else {
                    System.out.println("操作失败,该书尚未被借出\n");
                    return;
                }
            }
        }
        System.out.println("操作失败,本系统内不存在此书");
    }
}

和上面 Borrow 类同理,只需理清楚逻辑即可轻松写出代码


到现在,所有的代价都已经解析过啦,下面附上源码

三、源码

注意分清代码在=哪个包中的哪个类

// book 包
// Book类
public class Book {
    private String bookName;
    private String author;
    private double price;
    private boolean isBorrowed = false;

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

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

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

    public void setIsBorrowed(boolean isBorrowed) {
        this.isBorrowed = isBorrowed;
    }
}
// book 包
// BookShelf类
public class BookShelf {
    private Book[] books = new Book[10];
    private int size;

    public BookShelf() {
        books[0] = new Book("瓦尔登湖", "张三", 39.9);
        books[1] = new Book("百年孤独", "李四", 49.9);
        books[2] = new Book("赎罪", "王五", 38.8);
        this.size = 3;
    }

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

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

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public void printBookShelf(BookShelf bookShelf) {
        int size = bookShelf.getSize();
        for (int i = 0; i < size; i++) {
            System.out.print(i + 1 + ": ");
            System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + "  "
                    + "作者: " + bookShelf.getBooks()[i].getAuthor() + "  "
                    + "价格:"+ bookShelf.getBooks()[i].getPrice() + "元  "
                    + (bookShelf.getBooks()[i].getIsBorrowed()?"   已背借出":"   未被借出"));
        }
    }
}

// user 包
// USer 父类
public abstract class User {
    protected String name;
    protected Operate[] operates; //数组,存放不同的操作(对象)

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

    public abstract void menu();

    // 重点!
    public void doOperate(int operateOption, BookShelf bookShelf) {
        this.operates[operateOption].operate(bookShelf);
    }
}
// user 包
// Administrator 子类
public class Administrator extends User {
    // 构造方法
    public Administrator(String name) {
        super(name);
        this.operates = new Operate[]{
                new Exit(),
                new Show(),
                new Add(),
                new Delete(),
                new Find()
        };
    }

    public void menu() {
        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("——————————————");
    }
}
// user 包
// Customer 子类
public class Customer extends User{
    // 构造方法
    public Customer(String name) {
        super(name);
        this.operates = new Operate[]{
                new Exit(),
                new Find(),
                new Borrow(),
                new Return(),
        };
    }
    public void menu() {
        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("——————————————");
    }
}

// operate 包
// Operate 接口
public interface Operate {
    void operate(BookShelf bookShelf);
}
// operate 包
// Add 类
public class Add implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
        System.out.println("请依次输入:书名、作者、价格");

        Scanner scanner1 = new Scanner(System.in);
        String newBookName = scanner1.nextLine();
        Scanner scanner2 = new Scanner(System.in);
        String newAuthor = scanner2.nextLine();
        Scanner scanner3 = new Scanner(System.in);
        double newPrice = scanner3.nextDouble();

        int size = bookShelf.getSize();
        bookShelf.getBooks()[size] = new Book(newBookName, newAuthor, newPrice);
        System.out.println("增加成功\n");
        bookShelf.setSize(++size);
    }
}
// operate 包
// Delete 类
public class Delete implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
        int size = bookShelf.getSize();
        bookShelf.printBookShelf(bookShelf);

        System.out.print("请输入您要删除第几本书:");
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();

        for (int i = num - 1; i < size - 1; i++) {
            bookShelf.getBooks()[i] = bookShelf.getBooks()[i + 1];
        }
        bookShelf.setSize(--size);
        System.out.println("删除成功\n");

        bookShelf.printBookShelf(bookShelf);
    }
}
// operate 包
// Find 类 
public class Find implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
        System.out.println("请输入你要查询的书名");
        Scanner scanner = new Scanner(System.in);
        String targetName = scanner.nextLine();

        int size = bookShelf.getSize();
        for (int i = 0; i < size; i++) {
            if(bookShelf.getBooks()[i].getBookName().equals(targetName)) {
                System.out.println("该书籍信息如下:");
                System.out.println("书名: "+ bookShelf.getBooks()[i].getBookName() + "  "
                        + "作者: " + bookShelf.getBooks()[i].getAuthor() + " "
                        + "价格: "+ bookShelf.getBooks()[i].getPrice() + "元 "
                        + "是否被借出: " + bookShelf.getBooks()[i].getIsBorrowed());
                return;
            }
        }
        System.out.println("未查询到此书\n");
    }
}
// operate 包
// Exit 类 
public class Exit implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
        System.out.println("感谢使用本系统,再见!");
        System.exit(0);
    }
}
// operate 包
// Show 类 
public class Show implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
        System.out.println("图书信息如下:");
        bookShelf.printBookShelf(bookShelf);
    }
}
// operate 包
// Borrow 类 
public class Borrow implements Operate {
    @Override
    public void operate(BookShelf bookShelf) {
        System.out.println("请输入您要借阅的书名");
        Scanner scanner = new Scanner(System.in);
        String borrowName = scanner.nextLine();

        int size = bookShelf.getSize();

        for (int i = 0; i < size; i++) {
            if (bookShelf.getBooks()[i].getBookName().equals(borrowName)) {
                if(bookShelf.getBooks()[i].getIsBorrowed()) {
//                if (bookShelf.getBooks()[i].getIsBorrowed() == false) {
                    System.out.println("抱歉,该书已被借出\n");
                    return;
                }else {
                    bookShelf.getBooks()[i].setIsBorrowed(true);
                    System.out.println("借阅成功\n");
                    return;
                }
            }
        }
        System.out.println("操作失败,本系统内不存在此书");
    }
}
// operate 包
// Return 类 
public class Return implements Operate{
    @Override
    public void operate(BookShelf bookShelf) {
        System.out.println("请输入您要归还的书名");
        Scanner scanner = new Scanner(System.in);
        String borrowedName = scanner.nextLine();

        int size = bookShelf.getSize();

        for (int i = 0; i < size; i++) {
            if(bookShelf.getBooks()[i].getBookName().equals(borrowedName)) {
                if(bookShelf.getBooks()[i].getIsBorrowed()) {
//                if(bookShelf.getBooks()[i].getIsBorrowed() == true) {
                    bookShelf.getBooks()[i].setIsBorrowed(false);
                    System.out.println("归还成功\n");
                    return;
                }else {
                    System.out.println("操作失败,该书尚未被借出\n");
                    return;
                }
            }
        }
        System.out.println("操作失败,本系统内不存在此书");
    }
}

总结

以上就是本篇的全部内容了,虽然以目前所学的知识,写的图书管理系统还仅仅是皮毛,但结合了此前所学知识,是一个不错的巩固方式

博主认为难点主要在于
1️⃣如何 new 对象,new 什么对象?
2️⃣如何利用多态的思想
3️⃣如何利用接口
4️⃣最难的是如何面向对象,把这些知识串联起来,完整的写出这份代码

如果本篇对你有帮助,请点赞收藏支持一下,小手一抖就是对作者莫大的鼓励啦


上山总比下山辛苦
下篇文章见

你可能感兴趣的:(Java基础,java)