我要学编程(ಥ_ಥ)

我要学编程(ಥ_ಥ)

找往期文章包括但不限于本期文章中不懂的知识点:

顺序表的学习,点我 

目录

图书管理系统菜单

基本框架:

书:

书架: 

用户: 

实现基本功能 

新增图书:

借阅图书:

删除图书: 

退出系统: 

查找图书: 

归还图书: 

显示图书:


图书管理系统菜单

图书管理系统——Java版-LMLPHP

图书管理系统——Java版-LMLPHP

上面是根据选择不同用户,从而弹出的不同菜单。 

基本框架:

先把大的框架搭建出来。这里我们要用到三个对象:书、书架、用户。

书:

一些基本属性:

public class Book {
    private String name; // 书名
    private String author; // 作者
    private int price; // 价格
    private String type; // 类型
    private int count; // 数量
    private int lentCount; // 被借出的数量
}

用到private是为了防止所有人都可以拿到这些属性并且修改。

构造方法:

public Book(String name, String author, int price, String type, int count) {
        // 书一直在图书馆中,只有当新增或者删除才变动。而新增的书并不会一下子就被借出
        // 因此不需要初始化被借出的数量
        this.name = name;
        this.author = author;
        this.price = price;
        this.type = type;
        this.count = count;
    }

构造方法是为了在创建一个书的实例(新增)时初始化书的。 

getter 、setter 方法:

// 下面这些方法是用来修改书的状态的
    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 int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int getLentCount() {
        return lentCount;
    }

    public void setLentCount(int lentCount) {
        this.lentCount = lentCount;
    }

通过getter、setter方法来访问和修改书的属性。

重写toString 方法:

// 重写toString方法,以便于更好的打印
    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                ", count=" + count +
                ", lentCount=" + lentCount +
                '}';
    }

我们后面在查找和显示书时,要把书的全部信息给都给打印出来,因此得重写toString 方法。

书架: 

属性: 

public class BookList {
    // 书架里面原本应该有书才对
    // 书架是用来存放和管理书籍的,可以用顺序表(数组)来写
    private Book[] books = new Book[10]; // 为了方便,只放了3本书
    private int usedSize; // 书架已经使用的长度
}

getter、setter 方法:

    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;
    }

构造方法:

    // 初始化3本书
    public void func() {
        this.books[0] = new Book("Head First Java",
                "Kathy Sierra 、 Bert Bates",
                79, "计算机", 100);
        this.books[1] = new Book("Java 核心技术 卷I",
                "Cay S. Horstmann",
                119, "计算机", 100);
        this.books[2] = new Book("大话数据结构",
                "程杰", 59, "计算机", 100);
        this.usedSize = 3;
    }

    public BookList() {
        this.func();
    }

构造方法用来初始化书架的,也就是创建书的实例放到书架上。

用户: 

    public abstract class User{
    protected String name; // 因为这个name其子类也得使用
    public User(String name) {
        this.name = name;
    }

因为用户有两种,所以User肯定不能知道是哪一种。因此就用抽象类来写。

普通用户:

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

管理员用户: 

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

对象创建完毕,接下来就要开始让对象之间进行交互了。

前面我们看到了,不同的用户,根据选择的不同,会弹出不同功能菜单。这个有没有一种很熟悉的感觉,没错这就是我们在前面学习的多态。接下来就是要找多态的条件了:子类对象给到父类引用;子类重写父类当中的方法;通过父类引用调用被重写的方法。在上面的分析中,只有用户之间存在父子类关系。那么我们就可以在设计菜单时,根据选择的不同返回不同的用户对象。返回值就用父类接收,父类在调用功能菜单时,根据是哪一个子类,从而会调用不同的菜单。

登录菜单:

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

        System.out.println("请选择您的身份:1. 管理员;2. 普通用户");
        int n = scanner.nextInt();
        // 根据选择的不同,弹出不同的界面 (这里我们就可以采用多态的方式来写)

        while (true) {
            if (n == 1) {
                System.out.println("登录成功!");
                // 如果是管理员就返回管理员对象
                return new Administrators(name);
            }else if (n == 2) {
                System.out.println("登录成功!");
                // 如果是普通用户就返回普通用户对象
                return new RegularUsers(name);
            }else {
                System.out.println("登录失败,请重新选择您的身份!");
                n = scanner.nextInt();
            }
        }
    }

Main 方法: 

    public static void main(String[] args) {
        // 系统登录
        User user = login();
        // 创建一个书架
        BookList bookList = new BookList();
        while (true) {
            // 登录之后,就可以根据前面的选择弹出不同身份的界面
            int choice = user.menu();

            // 根据返回的选择,进行不同对象的不同的操作
            // 对象已经确定了,接下来,就是进行不同的操作。
            // 因为不同的对象包含不同的操作,所以我们可以把这个操作分成一个数组放到不同的类中
            user.work(choice, bookList); // 操作的对象是书架,因此传入书架
        }
    }

根据我们在功能页面的选择,来返回不同的值。接着调用work方法来实现不同的功能。这里同样运用了多态的思想。那么父类和子类同样都要有work方法。 

父类:

public abstract class User{
    protected String name; // 因为这个name其子类也得使用
    public User(String name) {
        this.name = name;
    }
    public abstract int menu();
    public abstract void work(int choice , BookList bookList);
}

子类:

public class RegularUsers extends User{
    protected IWork[] iWorks;
    public RegularUsers(String name) {
        super(name);
        // 注意顺序,要和功能菜单一致
        this.iWorks = new IWork[]{new Exit(), new FindBook(), new BorrowBook(), new ReturnBook()};
    }

    @Override
    public int menu() {
        System.out.println("*** 普通用户菜单 ***");
        System.out.println("1. 查找图书");
        System.out.println("2. 借阅图书");
        System.out.println("3. 归还图书");
        System.out.println("0. 退出系统");
        System.out.println("******************");
        System.out.print("请选择您要进行的操作:");
        Scanner scanner = new Scanner(System.in);
        int choice = scanner.nextInt();
        return choice;
    }
    public void work(int choice, BookList bookList) {
        // 通过对应的参数执行对应的操作
        iWorks[choice].work(bookList);
    }
}
public class Administrators extends User{
    IWork[] iWorks;
    @Override
    public int menu() {
        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.print("请选择您要进行的操作:");
        Scanner scanner = new Scanner(System.in);
        int choice = scanner.nextInt();
        return choice;
    }

    public Administrators(String name) {
        super(name);
        // 注意顺序,要和功能菜单一致
        this.iWorks = new IWork[]{new Exit(), new FindBook(), new AddBooks(), new DelBook(), new ShowBook()};
    }

    @Override
    public void work(int choice, BookList bookList) {
        iWorks[choice].work(bookList);
    }
}

因为操作是根据选择来分配的,也是可以用数组来进行接收,并且执行的。 

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

 上面是一个IWork的接口,为了实现用数组接收,并且更好的管理各种功能。

实现基本功能 

下面就是实现各种基本的功能了。

新增图书:

public class AddBooks implements IWork {

    @Override
    public void work(BookList bookList) {
        System.out.println("正在新增图书...");
        // 其实就是在这个顺序表的数组中新增了一个元素
        // 首先,得判断这个数组是否已经满了
        // 使用的长度如果等于书架的长度了,就需要增加书架的长度了
        if (bookList.getBooks().length == bookList.getUsedSize()) {
            System.out.println("书架已满,正在新增书架空间,请稍后...");
            // 创建一个新的数组
            Book[] newArray = Arrays.copyOf(bookList.getBooks(),2*bookList.getBooks().length);
            bookList.setBooks(newArray);
            System.out.println("书架空间新增成功!");
        }
        System.out.println("请输入要新增的书名:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        System.out.println("请输入要新增的书的作者:");
        String author = scanner.nextLine();
        System.out.println("请输入要新增的书的价格:");
        int price = scanner.nextInt();
        scanner.nextLine();
        System.out.println("请输入要新增的书的类型:");
        String type = scanner.nextLine();
        System.out.println("请输入要新增的书的数量:");
        int count = scanner.nextInt();

        // 判断该书是否已经存在。若已存在,只需把书的数量加上即可
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            if (bookList.getBooks()[i].getName().equals(name)) {
                System.out.println("该书已经存在了,因此增加数量即可");
                bookList.getBooks()[i].setCount(count + bookList.getBooks()[i].getCount());
                return;
            }
        }

        // 相当于 Books[4] = new Book(name, author, price, type, count);
        bookList.getBooks()[bookList.getUsedSize()] = new Book(name, author, price, type, count);
        bookList.setUsedSize(bookList.getUsedSize()+1);
        System.out.println("新增成功!");
    }
}

注意:Java中没有直接让数组空间大的方法,只能是拷贝一份比原来空间更大的数组。

借阅图书:

public class BorrowBook implements IWork{
    @Override
    public void work(BookList bookList) {
        System.out.println("正在借阅图书...");
        System.out.println("请输入您要借阅的书名:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            if (bookList.getBooks()[i].getName().equals(name)) {
                bookList.getBooks()[i].setLentCount(bookList.getBooks()[i].getLentCount()+1);
                System.out.println("书籍已自动发放到您的账户中,请注意查收!");
                return;
            }
        }
        System.out.println("对不起!暂时没有您要找的书,书库会尽快更新哦~");
    }
}

借阅图书就是把书架上的书的属性修改一下即可。

删除图书: 

public class DelBook implements IWork{
    @Override
    public void work(BookList bookList) {
        System.out.println("正在删除图书...");
        System.out.println("请输入您要删除的书名:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        // 注意这里查找与删除的范围
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            if (bookList.getBooks()[i].getName().equals(name)) {
                for (int j = i; j < bookList.getUsedSize()-1 ; j++) {
                    bookList.getBooks()[j] = bookList.getBooks()[j+1];
                }
                bookList.setUsedSize(bookList.getUsedSize()-1);
                System.out.println("删除成功!");
                return;
            }
        }
        System.out.println("对不起!没有您要删除的书");
    }
}

删除图书本质就是让有效的长度变小,并且让后面的元素覆盖前面的元素。

退出系统: 

public class Exit implements IWork{
    @Override
    public void work(BookList bookList) {
        System.out.println("正在退出图书管理系统...");
        System.exit(0);
    }
}

JavaAPI中提供了一个方法可以直接强制停止程序(正常停止),就是System.exit(0),参数一定要是0才行。这会立即终止当前Java虚拟机,其中的参数0表示正常退出状态。但请注意,除非确实需要立即终止整个JVM(比如在命令行应用中),否则通常建议让程序自然执行到结束而不是使用上面的方法,以允许JVM进行清理工作。

查找图书: 

public class FindBook implements IWork {
    @Override
    public void work(BookList bookList) {
        System.out.println("正在查找图书...");
        System.out.println("请输入您要查找的书名:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            if (bookList.getBooks()[i].getName().equals(name)) {
                System.out.println("下面是您要查找的书籍的相关信息:");
                System.out.println(bookList.getBooks()[i]);
                return;
            }
        }
        System.out.println("对不起!暂时没有您要找的书,书库会尽快更新哦~");
    }
}

查找图书就是遍历整个数组即可。

归还图书: 

 

public class ReturnBook implements IWork{
    @Override
    public void work(BookList bookList) {
        System.out.println("正在归还图书...");
        System.out.println("请输入您要归还的书名:");
        Scanner scanner = new Scanner(System.in);
        String name = scanner.nextLine();
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            if (bookList.getBooks()[i].getName().equals(name)) {
                bookList.getBooks()[i].setLentCount(bookList.getUsedSize()-1);
                System.out.println("归还成功!欢迎再次借书~");
                return;
            }
        }
        System.out.println("对不起!暂时没有您要归还的书~");
    }
}

显示图书:

public class ShowBook implements IWork {
    @Override
    public void work(BookList bookList) {
        System.out.println("正在显示图书...");
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            System.out.println(bookList.getBooks()[i]);
        }
    }
}

这里的显示图书,是显示所有图书,如果要显示单本图书,就是用查找图书的方法。

以上就是图书系统的基本功能啦!

这个图书系统是基于顺序表来实现的,如果有不懂的话,可以去看看那篇顺序表的博客(文章最前面)。

由于文件太多,不好全部把这些代码全部拷贝过来。

注意:上面的代码直接拷贝到编译器会报错的,因为没有导包,基本框架和IWork都是单独在包中的,Main方法是在源文件中单独存在的,并没有放入包中。

好啦!注意事项也讲完了,图书管理系统也基本实现啦!本期文章就到此结束啦!我们下一期再一起学习吧!

05-26 17:55