咱先不写代码,先分析一下一个图书管理系统最先需要的是什么?--书和用户.
并罗列出相关信息,大致如这样
这是书的相关代码
1.Book类:
package Library;
public class Book {
private String name;
private String author;
private double price;
private String type;
private boolean isBorrowed;
public Book(String name, String author, double price, String type) {
this.name = name;
this.author = author;
this.price = price;
this.type = type;
this.isBorrowed = false;//新增书默认为未借出状态
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
public double getPrice() {
return price;
}
public String getType() {
return 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 ? "Borrowed" : "Available") + "]";
}
}
2.BookList类
package Library;
//通过这个类,管理多个书籍对象
public class BookList {
private Book[] books = new Book[1000]; // 数组存放书籍对象,最大容量为1000
private int size = 0; // 记录书籍数量
public void setSize(int size) {
this.size = size;
}
public int getSize() {
return size;
}
public BookList() {
// 默认先填几本书,方便后续操作
//这样就可以按照任意顺序实现Operation,而无需先实现AddOperation
books[0] = new Book("Java入门", "Sun", 30,"Java基础教程");
books[1] = new Book("Python入门", "Peking University", 25,"Python基础教程");
books[2] = new Book("C++入门", "China University of Petroleum", 35,"C++基础教程");
books[3] = new Book("C语言入门", "Beijing University of Technology", 20,"C语言基础教程");
books[4] = new Book("Java入门", "Sun", 30,"Java基础教程");
size = 5; // 记录书籍数量
}
//IDEA提示默认是针对数组属性生成的getter和setter方法,更希望是针对数组的某个元素的getters和setters方法,
//public void setBooks(Book[] books) {
// this.books = books;
//}
//
// public Book[] getBooks() {
// return books;
// }
// 因此需要自定义自己需要的getters和setters方法,如下:
public Book getBook(int index) {
return books[index];
}
public void setBook(int index, Book book) {
books[index] = book;
}
}
写用户的代码实现之前我们除了考虑通过一个父类用户统一管理各个用户,还需要考虑用户如何对书进行操作
这里我们定义一个IOperation(接口)类型的数组operations,用于存储用户可以进行的具体操作,通过接口对各个操作进行统一处理.最后通过work方法实现对书的具体操作.
大致思路如下:
代码实现如下:
1.这是接口
package Library.Operation;
//既可以使用抽象类,也可以使用接口时,优先考虑接口,抽象类限制更多
//无属性优先考虑接口,有属性优先考虑抽象类
import Library.BookList;
//加上接口,强制work方法统一,限制代码的灵活性
//通过operation将书和用户关联起来
//而不是直接让用户操作书,这样有利于代码的解耦合
public interface IOperation {
//work方法,是针对书来进行的操作
void work(BookList bookList);
}
2.这是父类用户(User_father)
package Library.User;
import Library.BookList;
import Library.Operation.IOperation;
//所有用户的父类,包括管理员和普通用户
public abstract class User_father {
//protected修饰的变量可以直接被子类使用
protected String name;
//当前这个类,能够进行哪些操作,就可以添加到这个数组中
protected IOperation[] operations;
//构造方法,传入用户名
public User_father(String name) {
this.name = name;
}
//显示用户菜单,返回值是用户选择的选项序号
//使用abstract关键字声明menu()方法为抽象方法,避免出现父类实例化以及父类菜单;
public abstract int menu();
//普通用户类和管理员类都有菜单,
//但父类不知道会是什么菜单,所以可以直接使用abstract
//且用户中使用中不应该出现父类菜单或父类实例,
//所以这也能防止父类实例被不小心创建出来
public void work(int choice, BookList bookList){
if(choice < 0 || choice >= operations.length){
System.out.println("输入错误,请重新输入");
}
operations[choice].work(bookList);
//通过多态机制,根据用户的选择动态调用相应的操作类,并对 bookList 进行具体的增删改查等操作
}
}
3.子类1 NormalUser
package Library.User;
import Library.Operation.*;//导入操作接口
import java.util.Scanner;
public class NormalUser extends User_father {
public NormalUser(String name) {
super(name);
operations= new IOperation[]{
new ExitOperation(),
new ListOperation(),
new FindOperation(),
new BorrowOperation(),
new ReturnOperation()
};
}
@Override
public int menu() {
System.out.println("欢迎您," + name + "!" + "Normal User 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;
}
}
3.子类2 Administrator与NormalUser差不多(只是借阅和归还操作改为了增添和删除图书)
对书的具体操作我们以删除书籍为例,其他具体操作就不展示了
package Library.Operation;
import Library.Book;
import Library.BookList;
import java.util.Scanner;
public class DelOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("删除书籍");
//通过用户输入序号删除书籍
Scanner scanner = new Scanner(System.in);
System.out.print("请输入要删除的书籍序号:");
int index = scanner.nextInt();
if (index < 1 || index > bookList.getSize()) {
System.out.println("输入的序号不正确!");
return;
}
//如何删除数组中的指定元素?
//将最后一个元素复制到要删除的位置,然后删除最后一个元素,再size减一
//先判定当前这个元素是否是最后一个元素,如果不是,则将最后一个元素复制到当前元素的位置,然后删除最后一个元素,最后size减一
//如果当前元素是最后一个元素,则直接删除,最后size减一
if (index == bookList.getSize()-1) {
//如果当前元素是最后一个元素,则直接删除,最后size减一
bookList.setSize(bookList.getSize()-1);
System.out.println("删除成功!");
}
else {
//将最后一个元素复制到要删除的位置,然后删除最后一个元素,再size减一
// bookList.setBook(index, bookList.getBook(bookList.getSize()-1));
// bookList.setSize(bookList.getSize()-1);
// System.out.println("删除成功!");
//下面是优化后的代码
Book lastbook = bookList.getBook(bookList.getSize()-1);
bookList.setBook(index, lastbook);
bookList.setSize(bookList.getSize()-1);
System.out.println("删除成功!");
//即使删除,再次运行时仍会显示,
}
}
}
最后Main的实现
代码如下:
package Library;
//程序的入口类
import Library.User.Administrator;
import Library.User.NormalUser;
import Library.User.User_father;
import java.util.Scanner;
public class Main {
public static User_father login() {
//用户登录输入界面
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = scanner.nextLine();
System.out.println("请输入角色:(1.管理员 2.普通用户)");
int role = scanner.nextInt();
if (role == 1) {
return new Administrator(name);
} else if (role == 2) {
return new NormalUser(name);
} else {
return null;
}
}
public static void main(String[] args) {
//启动程序,构造主函数
//1.创建书籍管理对象
BookList bookList = new BookList();
//2.创建用户对象
User_father user = login();
//3.主循环
while (true) {
//4.显示菜单
int choice = user.menu();//menu触发多态
//5.根据用户选择执行相应操作
user.work(choice, bookList);
}
}
}
谢谢观看!