Java的三大特性是:封装、继承和多态。最近博主刚刚学完Java的三大特性,因此想写一个小项目巩固一下知识点。
这次的简单图书管理系统主要是为了练习继承,接口和多态的使用,那么就用这篇博客来讲解一下这个小项目,目的只是为了练习。
1、图书管理系统介绍
首先运行系统,需要先输入用户名称,接着选择身份(管理员/普通用户),如果是管理员,则打印管理员菜单,如果是普通用户则打印普通用户菜单,并等待接收执行指令编号,通过输入不同指令编号调用不同方法。
2、大致框架
图书管理系统,图书是一定需要的,要创建一个图书类,包括图书的书名、作者名、书的单价、书的类型、是否借出图书。用户也是一定需要的,所以要创建一个用户类。现在为了增加难度,我想要设置两个用户类:一个是管理员类,可以让管理员对图书进行管理,管理员对图书进行增删查改;一个就是普通的用户类,借阅归还图书。同时,两个类对应的菜单是不相同的。其他的内容就在写代码的时候在进行补充。
3、代码实现步骤
3.1、Book图书类
简单的对Book进行描述,并生成对应的get和set方法。然后重写继承于Object类的toSring()方法,方便后续打印图书内容。
package book; public class Book { private String name; //书名 private String author; private int price; private String type; private boolean isBorrowed; //是否被借出 成员变量默认值false public Book() { } 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 + '}'; } }
3.2、BookList书架类
书架类中包含了一个成员变量books,一个用于记录当前书架放了几本书的usedSize。
然后对BookList的空参构造函数进行编写:给books分配空间,这里设置固定大小10。接着初始化三个图书信息,用于表示当前书架中存在的图书。
写上对应的get和set方法,其中getBook方法是通过传入的下标得到指定的book,setBook是通过传入的下标和book,在对应下标处存入book。
package book; public class BookList { private Book[] books; private int usedSize;//记录当前书架放了几本书 public BookList() { this.books = new Book[10]; this.books[0] = new Book("三国演义","罗贯中",10,"小说"); this.books[1] = new Book("西游记","吴承恩",9,"小说"); this.books[2] = new Book("红楼梦","曹雪芹",19,"小说"); this.usedSize = 3; } public int getUsedSize() { return usedSize; } public void setUsedSize(int usedSize) { this.usedSize = usedSize; } public Book getBook(int pos) { return books[pos]; } public void setBook(Book book, int pos) { books[pos] = book; } }
3.3、User用户类、AdminUser类、NormalUser类
User
为了实现向上转型和多态,这里使用首先创建一个Uesr类,用于被AdminUser类和NormalUser类继承。
在User类中定义成员变量name,表示用户名。因为不同的身份打印的菜单是不一致的,因此User类中的menu()菜单方法写成抽象方法,在后面子类继承时再进行实现。
package user; import book.BookList; import operation.IOperation; public abstract class User { protected String name; public User(String name) { this.name = name; } public abstract int menu(); //抽象方法 }
NormalUser
NormalUser类继承User类并重写menu()方法。
package user; import operation.*; 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("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; } }
AdminUser
AdminUser类继承User类并重写menu()方法。
package user; import operation.*; import java.util.Scanner; public class AdminUser extends User{ public AdminUser(String name) { super(name); } @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.println("请输入你的操作:"); Scanner sc = new Scanner(System.in); int choice = sc.nextInt(); return choice; } }
3.4、IOperation操作接口
这里定义接口的目的是为了能够使后续创建的操作类能够被同一个对象接收,而只要这些操作类都实现了同一接口,就能够被统一接收,实现向上转型。
package operation; import book.BookList; public interface IOperation { void work(BookList bookList); }
3.5、继承IOperation接口的操作类
根据管理员和普通用户的菜单,操作类可以分为以下的七个:
- 新增图书AddOperation
- 借阅图书BorrowOperation
- 删除图书DelOperation
- 查找图书FindOperation
- 显示图书ShowOperation
- 归还图书ReturnOperation
- 退出系统ExitOperation
AddOperation
package operation; import book.Book; import book.BookList; import java.util.Scanner; public class AddOperation implements IOperation{ @Override public void work(BookList bookList) { Scanner sc = new Scanner(System.in); System.out.println("新增图书!"); System.out.println("请输入你要新增图书的书名:"); String name = sc.nextLine(); System.out.println("请输入你要新增图书的作者:"); String author = sc.nextLine(); System.out.println("请输入你要新增图书的价格:"); int price = sc.nextInt(); sc.nextLine(); //接收回车,sc.nextInt()不会读掉回车,所以需要先接收回车再进行。或者调换一下位置 System.out.println("请输入你要新增图书的类型:"); //nextInt和nextLine会存在冲突 String type = sc.nextLine(); Book book = new Book(name,author,price,type); int currentSize = bookList.getUsedSize(); for (int i = 0; i < currentSize; i++) { Book tmp = bookList.getBook(i); if(tmp.getName().equals(name)) { System.out.println("存在这本书,不能重复添加!"); return; } } bookList.setBook(book,currentSize); bookList.setUsedSize(currentSize+1); } }
BorrowOperation
package operation; import book.Book; import book.BookList; import java.util.Scanner; public class BorrowOperation implements IOperation { @Override public void work(BookList bookList) { System.out.println("借阅图书!"); Scanner sc = new Scanner(System.in); System.out.println("请写出你要借阅图书的书名:"); 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.setBorrowed(true); System.out.println("借阅成功!"); return; } } System.out.println("没有书名为'" + name + "'的书籍"); } }
DelOperation
package operation; import book.Book; import book.BookList; import java.util.Scanner; public class DelOperation implements IOperation { @Override public void work(BookList bookList) { Scanner sc = new Scanner(System.in); System.out.println("删除图书!"); System.out.println("请写出你要删除图书的书名:"); String name = sc.nextLine(); int currentSize = bookList.getUsedSize(); int index = -1; int i = 0; for (; i < currentSize; i++) { if (bookList.getBook(i).getName().equals(name)) { index = i; break; } } if (i > currentSize) { System.out.println("不存在书名为'" + name + "'的书籍,无法删除!"); return; } //使用移动覆盖作为删除 for (int j = index; j < currentSize - 1; j++) { Book book = bookList.getBook(j + 1); bookList.setBook(book, j); } //方便系统自动回收 bookList.setBook(null, currentSize - 1); bookList.setUsedSize(currentSize - 1); System.out.println("成功删除书名为'" + name + "'的书籍!"); } }
FindOperation
package operation; 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("不存在书名为‘"+name+"’的这本书!"); } }
ShowOperation
package operation; 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++) { Book book = bookList.getBook(i); System.out.println(book); } } }
ReturnOperation
package operation; import book.Book; import book.BookList; import java.util.Scanner; public class ReturnOperation implements IOperation{ @Override public void work(BookList bookList) { System.out.println("归还图书!"); Scanner sc = new Scanner(System.in); System.out.println("请写出你要归还图书的书名:"); 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.setBorrowed(false); System.out.println("归还成功!"); return; } } System.out.println("没有书名为'" + name + "'的书籍"); } }
ExitOperation
package operation; import book.BookList; public class ExitOperation implements IOperation{ @Override public void work(BookList bookList) { System.out.println("退出系统"); System.exit(0); } }
3.6、完善User类
在User类中定义一个成员数组iOperations用于存储各个操作类,但是因为User被两个身份的用户类继承,而不同用户又有不同的操作方法,因此此时只对成员数组iOperations声明,不进行初始化。对iOperations的初始化留给继承于User的两个用户类。
User
package user; import book.BookList; import operation.IOperation; public abstract class User { protected String name; protected IOperation[] iOperations; //初始化留给继承User的子类 public User(String name) { this.name = name; } public abstract int menu(); public void doOperation(int choice, BookList bookList) { this.iOperations[choice].work(bookList); //根据菜单的操作编号顺序确定iOperations数组中放置操作的顺序, //从而可以直接使用操作编号作为数组的下标来访问对应的work方法 } }
接着参照menu()菜单去NormalUser类和AdminUser类中对iOperation数组进行各自的初始化。
NormalUser
AdminUser
3.7、Mian类
所有需要的类都以及准备完毕,现在开始完成测试类Main。
- 其中login()方法会返回两个用户类中的一个给到user接收,此时发生了向上转型。
- 而根据login()方法得到的不同用户调用user.menu()会产生不同的菜单结果,此时说明发生了多态。
- 给user.doOperation()传入操作编号choice和书架对象bookList,达到调用与编号对应的操作。
import book.BookList; import operation.IOperation; 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.println("请输入你的名字:"); String name = sc.nextLine(); System.out.println("请输入你的身份, 1:管理员 2:普通用户 ==》"); 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(); //此时user指向的是【管理员】还是【普通用户】是不知道的 User user = login(); //向上转型 while (true) { int choice = user.menu(); //多态 //根据选择执行对应的操作 user.doOperation(choice,bookList); } } }
4、完整代码
由于篇幅有限,本篇博客的完整代码已上传到gitee,需要的小伙伴可以前往链接直接领取:
博主推荐:
【LeetCode力扣】42. 接雨水
如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!
如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!
如果觉得作者写的不错,求给博主一个大大的点赞支持一下,你们的支持是我更新的最大动力!