文章目录
✨✨✨学习的道路很枯燥,希望我们能并肩走下来!
编程真是一件很奇妙的东西。你只是浅尝辄止,那么只会觉得枯燥乏味,像对待任务似的应付它。但你如果深入探索,就会发现其中的奇妙,了解许多所不知道的原理。知识的力量让你沉醉,甘愿深陷其中并发现宝藏。
前言
本篇通过练习小型的图书管理系统,对java基础语法的进一步应用,提高对封装、继承、抽象、接口语法的熟练度。如有错误,请在评论区指正,让我们一起交流,共同进步!
本文开始
1. 小型图书管理系统框架思想
图书管理系统:顾名思义管理书的系统,他的功能有哪些?他的使用人群是哪些?
基本功能:
① 存储书的信息:
每本书book的基础信息:书名,价格,作者等
书架(存放各种书信息的地方):BookList,可以操作书的各种信息
② 面向的使用者:user
AdminUser:管理者(管理图书)对图书的增删改等信息的操作
NormalUser:正常使用者(借阅人)对图书查找,借阅等操作
③操作:对于使用者的各种操作,单独存放,使用接口调用操作对象
④主函数Main:让使用者根据User对象,做出具体什么操作
2. 实现框架
2.1 构建书架:存放书籍
定义一个包package: book =》关于书籍的操作
Book: 存放书的各种信息(一本) - 是一个类
BookList: 多本书,使用数组存储Book[ ]
Book 代码实现:
对于书的属性实现了封装:所以需要提供get,set方法,以便于操作书里面的属性
package book;
public class Book {
private String name;//书名
private String author;
private int price;
private String type;
private boolean isBorrowed;//是否被借出
//isBorrowed不需要初始化,开始的时候,书都是未被借出的默认赋值为false
//当书真正被借出时,我们之间修改isBorrowed属性即可
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 +
(isBorrowed ? " 已被借出 " : " 未被借出 ")+
//利用三木表达式判断是否借出
'}';
}
}
BookList 代码实现:
定义常量DEFAULT_SIZE 可以及时更改存放书的数量
书架里面封装了数组:Book[ ]可以存放多本书
usedSize: 记录书架上书的多少
【注】
这里也是封装了元素,但是出现的构造方法getBooks,setBooks不符合我们的期望,返回的是数组Book[ ], 这里只是构建框架,下面具体操作会详细说明情况!
package book;
public class BookList {
private static final int DEFAULT_SIZE = 5;
private Book[] books = new Book[DEFAULT_SIZE];
private int usedSize;
//借书是一本本借,所以需要操作的一本书,而不是书的数组
// 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;
}
}
2.2 使用者的构建 - user
这里我们提出两种使用者:管理者和正常使用者
我们通过思考代码实践,会发现他们会有共同的属性或方法,这时可以抽象出一个类User存放他们共有的元素;
而对应管理者和正常使用者,他们的基本操作大致是一样的,只有具体的操作略有不同;
User为什么是抽象类?
主函数首先需要调用login需要显示菜单,但是父类对象没有办法使用子类里面的方法,所以menu()写成抽象方法,进而User类改成抽象类;父类再调用时发生运行时绑定,会调用子类menu()方法
User代码的实现:
package user;
import book.BookList;
public abstract class User {
public String name;
public User(String name) {
this.name = name;
}
//主函数调用login需要显示菜单,但是父类对象没有办法使用子类里面的方法,
// 所以menu()写成抽象方法,进而User类改成抽象类
// 父类再调用时发生运行时绑定,会调用子类menu()方法
public abstract int menu();
}
管理者代码实现:
知道管理者姓名,就显示可操作的菜单,根据菜单进行具体的增删改等操作
package user;
import operate.*;
import java.util.Scanner;
public class AdminUser extends User{
//知道对象的时候,构造方法会初始化name
public AdminUser(String name) {
super(name);
}
@Override
public int menu() {
System.out.println("=======================");
System.out.println("hello " + name + " 欢迎使用图书系统!");
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;
}
}
正常使用者代码实现
import operate.*;
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("hello " + name + " 欢迎使用图书系统!");
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;
}
}
2.3 主函数构建 - Main
主函数中,使用者首先需要见到登录页面,确定登录身份输入0 或 1 确定管理者还是正常使用者,再返回对应的对象菜单;
login(): 登录操作,调用login返回对象有两种结果,所以使用(返回值类)向上转型,通过父类可以介绍多种子类对象;
import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
public class Main {
public static User login() {//发生向上转型:返回值
System.out.println("请输入姓名:>");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
System.out.println("请输入你的身份:1:管理者,0:借阅者 ");
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();
//调用login返回的对象不确定需要父类对象来接受
User user = login();
//通过登录确认使用对象
//显示登录对象的菜单,从而进行操作
while (true) {//利用循环进行多次操作
user.menu();//根据对象调用菜单
}
}
}
2.4 操作的构建 - operate
对于各种操作,都有不同的操作,我们可以定义一个接口,让所有操作implements接口,这样连接这个接口的对象都可以被同一个接口调用;
接口代码实现
package operate;
import book.BookList;
public interface IOPeration {
void work(BookList bookList);
}
使用者的各种操作连接这个接口即可;
管理者基本操作:
查找图书:FindOperation
增加图书:AddOperation
删除图书:DelOperation
显示图书:ShowOperation
退出系统:ExitOperation
正常使用者基本操作:
查找图书:FindOperation
借阅图书:BorrowOperation
归还图书:DelOperation
退出系统:ExitOperation
2.5 对象与操作建立联系
使用者与操作建立联系:IOPeration [ ]
刚才建立了接口,可以通过接口数组存放使用者的操作对象 IOPeraton[ ]
由于都需要操作,所以接口数组,也需要定义在User中;
主函数与操作建立联系:doWork()
主函数中login()会返回对象,再根据菜单menu()返回具体选择choice,把选择与书架对象以参数形式传给doWork();
doWork()具体工作: 根据操作数组找到对象,在操作具体的工作; this.ioPerations[choice].work(bookList);
this.ioPeration[choice] => 根据选择找到操作的对象;work(bookList) => 操作对象的具体工作
更新User代码:
package user;
import book.BookList;
import operate.IOPeration;
public abstract class User {
public String name;
public IOPeration[] ioPerations;//操作数组存储操作对象
public User(String name) {
this.name = name;
}
public abstract int menu();
public void doWork(int choice, BookList bookList) {
this.ioPerations[choice].work(bookList);
//this.ioPeration[choice] => 根据选择找到操作的对象
//work(bookList) => 操作对象的具体工作
}
}
main代码更新:
public static void main(String[] args) {
BookList bookList = new BookList();
User user = login();
//通过登录确认使用对象
//显示登录对象的菜单,从而进行操作
while (true) {//利用循环进行多次操作
int choice = user.menu();//根据对象调用菜单,返回操作的选择
user.doWork(choice,bookList);
}
}
3. 细化各种操作内容
3.1 增加图书:AddOperation
输入图书的各种信息,再通过new对象,把书的参数给book, 再通过引用把书存放到usedSize位置,最后记录书的数量+1;
【注】通过循环查询增加的图书是否存在, 这里我们认为一本书只能存一本
增加书的代码实现:
package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class AddOperation implements IOPeration{
@Override
public void work(BookList bookList) {
System.out.println("新增图书! ");
Scanner sc = new Scanner(System.in);
System.out.println(" 输入书名: ");
String name = sc.nextLine();
System.out.println(" 输入作者:");
String author = sc.nextLine();
System.out.println(" 输入类型:");
String type = sc.nextLine();
System.out.println(" 输入价格:");
int price = sc.nextInt();
Book book = new Book(name,author,price,type);
int currentSize = bookList.getUsedSize();
//判断书架上是否有此书,有就不能存入了
for (int i = 0; i < currentSize; i++) {
Book t = bookList.getBook(i);
if(t.getName().equals(name)) {
System.out.println("此书已存在,不能再放入!");
break;
}
}
//直接在最后位置存书
bookList.setBooks(book);
bookList.setUsedSize(currentSize+1);
System.out.println("存入成功!");
}
}
3.2 借阅图书:BorrowOperation
通过循环遍历,查看书是否有,状态是否是未被借出的状态;
书是对象,需要引用来获得(bookList.getBook());
因为是引用对象,比较其中的内容需要使用equals()方法;
【注】书被借出去了,记得改变书的状态
借阅图书代码实现:
package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class BorrowOperation 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) && !book.isBorrowed()) {
book.setBorrowed(true);
System.out.println("借阅成功!");
}
}
}
}
3.3 删除图书:DelOperation
循环找到删除图书的下标,根据下标从后往前覆盖要删除的对象,使用getBook()获取删除下标的下一个位置,使用setBook()把书覆盖到前一个位置;因为是对象最后需要把最后一个位置置null;
【注】统计书架大小的需要-1;为了防止下标越界需要循环结束条件为当前书的数量-1;
删除书代码实现:
package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class DelOperation 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();
int index = -1;
//循环找到删除图书的下标位置
for (int i = 0; i < currentSize; i++) {
Book t = bookList.getBook(i);
if(t.getName().equals(name)) {
index = i; //记录删除图书的位置
break;
}
}
//删除图书:都是封装的对象,需要引用变量
for (int j = index; j < currentSize-1; j++) {
Book book = bookList.getBook(j+1);//找到j+1下标的图书
bookList.setBooks(j,book);//把书放到j下标位置
}
//修改usedSize
bookList.setUsedSize(currentSize-1);
//删除的是对象,最后一个位置需要置null
bookList.setBooks(currentSize-1,null);
System.out.println("删除成功!");
}
}
3.4 查找图书:FindOperation
根据输入的书名,与存在的书相比较,如果有相同的即输出这本书的信息;
package operate;
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("不存在这本书!");
}
}
3.5 归还图书操作:ReturnOperation
输入归还图书的书名,比较书架上的书名与借的书名是否有相同的,并且书还是被借出去的(isBorrowed状态为ture)
【注】存在书名,归还后需要修改书的状态为false
归还书的代码操作实现:
package operate;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class ReturnOperation 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);
//比较书架上的书名与借的书名是否有相同的,并且书还是被借出去的(isBorrowed状态为ture)
if(book.getName().equals(name) && book.isBorrowed()) {
book.setBorrowed(false);
System.out.println("归还成功");
return;
}
}
}
}
3.6 显示存在的图书:ShowOperation
通过循环输出显示结果,不能直接使用bookList[i]打印,这是引用对象,需要打印book对象,调用会调用重写的toString()方法,显示图书信息;
显示图书代码操作:
package operate;
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++) {
//System.out.println(bookList[i]);
Book book = bookList.getBook(i);
System.out.println(book);//通过调用重写的toString()显示书的内容
}
}
}
3.7 退出系统:ExitOperation
系统退出操作,输入0为一般退出操作
退出系统代码实现:
package operate;
import book.BookList;
public class ExitOperation implements IOPeration{
@Override
public void work(BookList bookList) {
System.out.println("退出系统!");
//输入0即为退出系统,系统退出的操作
System.exit(0);
}
}
4. 总体代码
操作代码的详细内容为上述代码细化的内容;
//关于书信息的包下内容
package book;
public class Book {
private String name;//书名
private String author;
private int price;
private String type;
private boolean isBorrowed;//是否被借出
//书的元素被封装:所以需要提供构造方法,以便于操作书里面的属性
//isBorrowed不需要初始化,开始的时候,书都是未被借出的默认赋值为false
//当书真正被借出时,我们之间修改isBorrowed属性即可
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 +
(isBorrowed ? " 已被借出 " : " 未被借出 ")+
'}';
}
}
//书架内容
package book;
public class BookList {
private static final int DEFAULT_SIZE = 5;
private Book[] books = new Book[DEFAULT_SIZE];
private int usedSize;
public BookList() {
books[0] = new Book("三国","罗贯中",43,"小说");
books[1] = new Book("西游记","吴承恩",40,"小说");
books[2] = new Book("红楼梦","罗贯中",45,"小说");
this.usedSize = 3;
}
public Book getBook(int pos) {
return this.books[pos];
}
//AddOperation操作时直接在useSize位置添加图书
public void setBooks(Book book) {
this.books[usedSize] = book;
}
//DelOperation操作时,设置pos位置的值
public void setBooks(int pos,Book book) {
this.books[pos] = book;
}
public int getUsedSize() {
return usedSize;
}
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
}
//使用者包下的代码:
package user;
import book.BookList;
import operate.IOPeration;
public abstract class User {
public String name;
public IOPeration[] ioPerations;//操作数组存储操作对象
public User(String name) {
this.name = name;
}
//主函数调用login需要显示菜单,但是父类对象没有办法使用子类里面的方法,
// 所以menu()写成抽象方法,进而User类改成抽象类
// 父类再调用时发生运行时绑定,会调用子类menu()方法
public abstract int menu();
public void doWork(int choice, BookList bookList) {
this.ioPerations[choice].work(bookList);
//this.ioPeration[choice] => 根据选择找到操作的对象
//work(bookList) => 操作对象的具体工作
}
}
//管理者
package user;
import operate.*;
import java.util.Scanner;
public class AdminUser extends User{
//知道对象的时候,构造方法会初始化name,初始化接口数组(管理者5个对象,借阅者4个对象)
public AdminUser(String name) {
super(name);
//引用变量赋值,需要动态赋值:需要new一下;根据数组的下标调用操作对象
this.ioPerations = new IOPeration[] {
new ExitOperation(),
new FindOperation(),
new AddOperation(),
new DelOperation(),
new ShowOperation()
};
}
@Override
public int menu() {
System.out.println("=======================");
System.out.println("hello " + name + " 欢迎使用图书系统!");
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;
}
}
//普通使用者
package user;
import operate.*;
import java.util.Scanner;
public class NormalUser extends User{
public NormalUser(String name) {
super(name);
this.ioPerations = new IOPeration[] {
new ExitOperation(),
new FindOperation(),
new BorrowOperation(),
new ReturnOperation()
};
}
@Override
public int menu() {
System.out.println("=======================");
System.out.println("hello " + name + " 欢迎使用图书系统!");
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;
}
}
//主函数:
import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
public class Main {
public static User login() {//发生向上转型:返回值
System.out.println("请输入姓名:>");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
System.out.println("请输入你的身份:1:管理者,0:借阅者 ");
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();
//调用login返回的对象不确定需要父类对象来接受
User user = login();
//通过登录确认使用对象
//显示登录对象的菜单,从而进行操作
while (true) {//利用循环进行多次操作
int choice = user.menu();//根据对象调用菜单,返回操作的选择
user.doWork(choice,bookList);
}
}
}
总结
✨✨✨各位读友,本篇分享到内容如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!