目录
一、图书管理系统应具备的功能
1、图书管理系统有两种用户:管理员和普通用户;
2、两种用户所具有的功能列表不一样:
管理员的功能:查找图书、新增图书、删除图书、显示图书、退出系统。
普通用户的功能:查找图书、借阅图书、归还图书、退出系统。
二、简单分析如何实现该系统
1、图书肯定有很多种,而每种图书都有书名、作者、类型等属性,那么我们就可以把图书抽象为一个类——Book;
2、我们可以创建一个Book类类型的数组,用于存放系统中的每一种图书;
3、上面创建的数组我们可以把它存放在一个书架类——BookShelf中,并且在BookShelf类中实现一些对数组进行基本操作的方法,比如获取数组中的某个元素,设置数组中的某个元素等等;
4、系统有两种用户,而两种用户的功能不同,我们可以把它们分别抽象为一个类,因为每种用户的功能不一样,那么我们可以再给它们创造一个共同的父类——User类,通过重写父类的方法和向上转型,就可以为两种用户提供不同的功能;
5、每种功能如何具体实现呢?我们可以创建一个接口——Operation,接口中写一个work()方法,而每种功能可以抽象为一个类,这些类只要实现了这个接口并重写其中的work()方法,那么在之后调用时就会很方便。
6、最后在main()函数中写一个登录方法——login(),并把相关操作放入到一个while循环中即可。
三、框架图
四、代码实现过程及简析
1、Book类
package Book;
public class Book {
private String bookName; //书名
private String authorName; //作者
private String type; //类型
private int quantity; //数量
//构造方法
public Book(String bookName, String authorName, String type, int quantity) {
this.bookName = bookName;
this.authorName = authorName;
this.type = type;
this.quantity = quantity;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
@Override
public String toString() {
return "Book{" +
"书名《" + bookName + "》" +
"作者:" + authorName +
", 类型:" + type +
", 图书数量:" + quantity +
", 是否可借阅:" + ((quantity > 0)?
("可以借阅"):("图书数量不足,无法借阅")) +
'}';
}
}
简析:
Book类中有图书的书名、作者、类型、数量这些基本属性和相对应的get、set方法,以及Book类的构造方法和toString方法,构造方法用于实现之后的新增图书功能,toString方法用于实现之后的显示图书信息和查找图书功能。
2、BookShelf类
package Book;
public class BookShelf {
private Book[] books = new Book[10];
private int kindOfBooks ;//当前书架中图书的种类
public BookShelf(){
books[0] = new Book("西游记","吴承恩","小说",2);
books[1] = new Book("红楼梦","曹雪芹","小说",5);
books[2] = new Book("水浒传","施耐庵","小说",1);
books[3] = new Book("三国演义","罗贯中","小说",10);
kindOfBooks = 4;
}
//获取当前图书种类
public int getKindOfBooks() {
return kindOfBooks;
}
//设置当前图数种类
public void setKindOfBooks(int kindOfBooks) {
this.kindOfBooks = kindOfBooks;
}
//获取当前位置的图书
public Book getBook(int local){
return books[local];
}
//设置当前位置的图书
public void setBook(int local, Book book){
books[local] = book;
}
//删除当前位置的图书
public void delBook(int ret) {
books[ret] = books[ret + 1];
}
}
简析:
BookShelf类中我们给了两个成员变量,一个是book类类型的数组,用于存储每一种图书,另一个是获取当前图书种类的一个int类型变量,并给出了相应的get、set方法(一些方法稍作修改)和一个无参的构造方法,在这个构造方法中我们给数组初始化了4个元素,只要实例化一个BookShelf类的对象,我们的书架中就会有这四本书。
3、IOperation接口
package Operation;
import Book.BookShelf;
public interface IOperation {
void work(BookShelf bookShelf);
}
简析:接口中只有一个抽象方法work(),它的参数是一个Bookshelf类的对象。
3.1 AddOperation类
package Operation;
import Book.Book;
import Book.BookShelf;
import java.util.Scanner;
public class AddOperation implements IOperation{
@Override
public void work(BookShelf bookShelf) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要新增的图书名:");
String newBookName = scanner.nextLine();
System.out.println("请输入图书的作者:");
String authorName = scanner.nextLine();
System.out.println("请输入图书类型");
String bookType = scanner.nextLine();
System.out.println("请输入新增图书数量");
int bookQuantity = scanner.nextInt();
//如果新增的图书是系统中已有的图书,那么只需增加图书数量即可
int ret = bookShelf.getKindOfBooks();//获取当前图书种类
for (int i = 0; i < ret ; i++) { //遍历书架中的图书
String str = bookShelf.getBook(i).getBookName();//获取当前图书的书名
if(str.equals(newBookName)){
int quantity = bookShelf.getBook(i).getQuantity();//获取当前图书的数量
bookShelf.getBook(i).setQuantity(quantity+bookQuantity);//更新当前图书的数量
System.out.println("新增图书成功");
return;
}
}
//如果新增的图书是系统中没有的图书:
bookShelf.setBook(ret,new Book(newBookName,authorName,bookType,bookQuantity));
bookShelf.setKindOfBooks(ret+1);//不要忘记更新图书种类
System.out.println("新增图书成功");
}
}
3.2 BorrowOperation类
package Operation;
import Book.BookShelf;
import java.util.Scanner;
public class BorrowOperation implements IOperation{
@Override
public void work(BookShelf bookShelf) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要借阅的图书名:");
String name = scanner.nextLine();
int ret = bookShelf.getKindOfBooks();//获取当前图书种类
for (int i = 0; i < ret ; i++) { //遍历书架中的图书
String str = bookShelf.getBook(i).getBookName(); //获取当前图书的书名
int quantity = bookShelf.getBook(i).getQuantity();//获取当前图书的数量
if(str.equals(name) && quantity > 0){ //书名相同,并且数量足够才可以借阅
bookShelf.getBook(i).setQuantity(quantity - 1);//更新当前图书的数量
System.out.println("借阅图书成功");
return;
}
if(quantity <= 0) {
System.out.println("图书数量不足,借阅失败");
return;
}
}
System.out.println("找不到这本书,借阅失败");
}
}
3.3 DeleteOperation类
package Operation;
import Book.Book;
import Book.BookShelf;
import java.util.Scanner;
public class DeleteOperation implements IOperation {
@Override
public void work(BookShelf bookShelf) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要删除的图书名:");
String newBookName = scanner.nextLine();
int ret = bookShelf.getKindOfBooks();//获取当前图书种类
for (int i = 0; i < ret ; i++) { //遍历书架中的图书
String str = bookShelf.getBook(i).getBookName();//获取当前图书的书名
if(str.equals(newBookName)){
for (int j = i; j < ret; j++) {
bookShelf.delBook(j);
}
bookShelf.setKindOfBooks(ret-1);//不要忘记更新图书种类
System.out.println("删除图书成功");
return;
}
}
System.out.println("系统中没有这本书,删除图书失败");
}
}
3.4 DisplayOperation类
package Operation;
import Book.Book;
import Book.BookShelf;
public class DisplayOperation implements IOperation{
@Override
public void work(BookShelf bookShelf) {
System.out.println("当前系统中图书信息如下:");
int ret = bookShelf.getKindOfBooks();//获取当前图书种类
for (int i = 0; i < ret ; i++) { //遍历书架中的图书
System.out.println(bookShelf.getBook(i).toString());//打印图书信息
}
}
}
3.5 ExitOperation类
package Operation;
import Book.BookShelf;
public class ExitOperation implements IOperation{
@Override
public void work(BookShelf bookShelf) {
System.out.println("退出系统");
System.exit(0);//给个参数0,表示程序正常结束
}
}
3.6 ReturnOperation类
package Operation;
import Book.BookShelf;
import java.util.Scanner;
public class ReturnOperation implements IOperation{
@Override
public void work(BookShelf bookShelf) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要归还的图书名:");
String newBookName = scanner.nextLine();
int ret = bookShelf.getKindOfBooks();//获取当前图书种类
for (int i = 0; i < ret ; i++) { //遍历书架中的图书
String str = bookShelf.getBook(i).getBookName();//获取当前图书的书名
if(str.equals(newBookName)){
int quantity = bookShelf.getBook(i).getQuantity();//获取当前图书的数量
bookShelf.getBook(i).setQuantity(quantity + 1);//更新当前图书的数量
System.out.println("归还图书成功");
return;
}
}
System.out.println("系统中没有这本书,归还失败");
}
}
3.7 SearchOperation类
package Operation;
import Book.Book;
import Book.BookShelf;
import java.util.Scanner;
public class SearchOperation implements IOperation{
@Override
public void work(BookShelf bookShelf) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要查找的图书名:");
String newBookName = scanner.nextLine();
int ret = bookShelf.getKindOfBooks();//获取当前图书种类
for (int i = 0; i < ret ; i++) { //遍历书架中的图书
String str = bookShelf.getBook(i).getBookName();//获取当前图书的书名
if(str.equals(newBookName)){
System.out.println("图书信息如下:");
System.out.println(bookShelf.getBook(i).toString());
return;
}
}
System.out.println("系统中没有这本书,查找失败");
}
}
重写这几个类中的work方法时,终于感受到了面向对象思想的强大!
4、User类
package User;
import Book.BookShelf;
import Operation.IOperation;
public abstract class User {
protected String userName;
protected IOperation[] iOperations;
public User(String userName) {
this.userName = userName;
}
public abstract int menu();
public void doOperation(int choice, BookShelf bookShelf){
this.iOperations[choice].work(bookShelf);
}
}
简析:
抽象父类User中,我们给了一个用户名和初始化它的构造方法;还有一个Operation引用类型的数组,这个数组在子类中会用到;一个抽象方法menu(),用来让子类重写自己的功能菜单;还有一个doOperation()方法,用来实现子类所对应的图书管理功能。
5、AdminUser类
package User;
import Operation.*;
import java.util.Scanner;
public class AdminUser extends User{
public AdminUser(String userName) {
super(userName);
this.iOperations = new IOperation[]{
new ExitOperation(),
new SearchOperation(),
new AddOperation(),
new DeleteOperation(),
new DisplayOperation()
};
}
@Override
public int menu(){
System.out.println("Hello,管理员"+this.userName+",欢迎进入图书管理系统");
System.out.println("1.查找图书");
System.out.println("2.新增图书");
System.out.println("3.删除图书");
System.out.println("4.显示图书");
System.out.println("0.退出系统");
System.out.println("请选择你要进行的操作:");
Scanner scanner = new Scanner(System.in);
int choice = 0;
while(true) {
choice = scanner.nextInt();
if (choice < 0 || choice > 4) {
System.out.println("请选择正确的操作");
}
else {
break;
}
}
return choice;
}
}
简析:
在子类AdminUser中,我们给了一个构造方法来初始化父类中的用户名,同时给IOperation引用类型的这个数组进行了初始化,数组中的元素下标与功能菜单中的选项数字相对应;然后重写了父类中的menu()方法,给出了相应的功能菜单。
6、NormalUser类
package User;
import Operation.*;
import java.util.Scanner;
public class NormalUser extends User{
public NormalUser(String userName) {
super(userName);
this.iOperations = new IOperation[]{
new ExitOperation(),
new SearchOperation(),
new BorrowOperation(),
new ReturnOperation()
};
}
@Override
public int menu(){
System.out.println("Hello,"+this.userName+",欢迎来到图书馆");
System.out.println("1.查找图书");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("0.退出系统");
System.out.println("请选择你要进行的操作:");
Scanner scanner = new Scanner(System.in);
int choice = 0;
while(true) {
choice = scanner.nextInt();
if (choice < 0 || choice > 3) {
System.out.println("请选择正确的操作");
}
else {
break;
}
}
return choice;
}
}
简析:
和AdminUser类一样,在NormalUser子类中,我们给出了初始化父类的构造方法,并同时初始化了数组内容,数组元素下标与菜单功能中的选项数字相同,也重写了menu()方法,给出了相应的功能菜单。
7、Main类
package User;
import Book.BookShelf;
import java.util.Scanner;
public class Main {
public static User login(){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = scanner.nextLine();
System.out.println("请选择你的身份:1.管理员 0.普通用户");
int choice = 0;
while(true) {
choice = scanner.nextInt();
if(choice == 0){
return new NormalUser(name);
}else if(choice == 1){
return new AdminUser(name);
}else{
System.out.println("请选择正确的操作");
}
}
}
public static void main(String[] args) {
User user = login();
BookShelf bookShelf = new BookShelf();
while (true){
int choice = user.menu();
user.doOperation(choice,bookShelf);
}
}
}
简析:
在Main类中,写了整个系统的main方法,进入main方法,首先调用login方法来登录,根据用户的选择来确定对应的身份。
(注意,login方法的返回值类型是父类User,而返回的确是子类的对象,所以在这个过程中发生了向上转型)
然后实例化一个BookShelf对象,在一个死循环中,通过返回的user来调用子类的menu方法,根据menu方法的返回值和BookShel对象,调用父类的doOperation方法即可调用功能菜单中相应的功能。
思维导图:
谢谢大佬的阅读~