找往期文章包括但不限于本期文章中不懂的知识点:
目录
图书管理系统菜单
上面是根据选择不同用户,从而弹出的不同菜单。
基本框架:
先把大的框架搭建出来。这里我们要用到三个对象:书、书架、用户。
书:
一些基本属性:
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方法是在源文件中单独存在的,并没有放入包中。
好啦!注意事项也讲完了,图书管理系统也基本实现啦!本期文章就到此结束啦!我们下一期再一起学习吧!