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


前言

📕各位读者好, 我是小陈, 这是我的个人主页
📗小陈还在持续努力学习编程, 努力通过博客输出所学知识
📘如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽
📙 希望我的专栏能够帮助到你:
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”

在这里插入图片描述

所以👉我们在 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️⃣最难的是如何面向对象,把这些知识串联起来,完整的写出这份代码

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


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

  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
摘 要 统一建模语言UML是面向对象分析和设计过程中重要的建模工具,本文以图书管理系统的开发为背景,介绍了UML的分析和建模过程。 关键词 UML;系统分析;建模设计 1 UML简介 UML(统一建模语言)是面向对象建模语言的标准,它可以对任何具有静态结构和动态行为的系统进行建模,它的主要作用是帮助用户进行面向的描述和建模,它可以描述软件从需求分析到软件实现和测试的全过程。标准建模语言UML的重要内容可以由五类图(十种图形)来定义,如表1所示。 表1 UML模型种类 序号 模型种类 十种图形 建模机制 1 用例模型 用例图 静态建模 2 静态模型 类图、对象图、包图 静态建模 3 行为模型 状态图、活动图 动态建模 4 交互模型 顺序图、协作图 动态建模 5 实现模型 构件图、配置图 静态建模 2 图书管理系统的UML建模设计 以图书管理系统为例,结合Rational Rose2003工具软件绘制图形,详细阐述UML的建模过程。 2.1 需求分析描述 图书信息管理系统是使用计算机实现图书大量信息处理的电子档案管理系统,在本系统中主要满足借书者、图书管理员和系统管理员3方面的需求。对借书者来说主要是查询个人信息、查询图书信息、预定当前正在被别人借阅的图书、借阅图书和返还图书等;图书管理员是系统的主要使用者,负责借书处理和还书处理,当读者预定的图书借出给定预定者后取消图书预定;系统管理员主要负责系统的维护工作,涉及到读者信息管理,图书信息管理,系统状态维护等。系统的功能分析如图1所示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵魂相契的树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值