文章目录
JavaProject & 经典图书管理系统
- 我们学习了一些java基础语法之后,以及了解到了面向对象的三大特征之后,我们结合这些知识,来实践一下吧!
图书管理功能大体要求:
- 一本书有不同属性
- 书名
- 也可将书名跟书内容联系起来,附上字符串链接(这里我省略了)
- 书类
- 价格
- 作者
- 是否被借
- 借书之人
- 书名
- 所有书放在 书架(数组) 上
- 来访者的身份
- 管理员
- 普通用户
- 不同身份的权限
- 管理员
- 添书
- 删书
- 查书
- 查看书单
- 退出系统
- 普通用户
- 查书
- 借书
- 还书
- 退出系统
- 管理员
根据要求制作模板:
Ⅰ.构建Book类
- 基本属性
public class Book {
private String name;
private String author;
private Double price;
private String type;
private boolean state;
private String Borrower;
}
- 基本方法
- 不必害怕,只不过是一些
构造方法
和getter()
和setter()
以及重写toString
- IDEA有快捷方式—> Alt + Enter
- 不必害怕,只不过是一些
public String getBorrower() {
return Borrower;
}
public void setBorrower(String borrower) {
Borrower = borrower;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", type='" + type + '\'' +
", " + (state ? "已被借出" : "未被借出") +
'}';
}
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 Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isState() {
return state;
}
public void setState(boolean state) {
this.state = state;
}
public Book(String name, String author, Double price, String type) {
this.name = name;
this.author = author;
this.price = price;
this.type = type;
}
Ⅱ. 进入系统页面基本操作&菜单
- 如上图的管理员菜单和普通用户菜单【管理员可以设立密码】
Ⅲ. 书架搭建
- 默认三本书
- 满了就动态扩容—>参考Java数组章节
public class BookList {
private Book[] books = new Book[5];
private int number = 3;
private int capacity = 5;
{
books[0] = new Book("小王子1", "王子1", 99.9, "学习");
books[1] = new Book("小王子2", "王子2", 99.9, "学习");
books[2] = new Book("小王子3", "王子3", 99.9, "学习");
}
}
- 调整
toString()
方法
@Override
public String toString() {
String str = "";
for (int i = 0; i < number; i++) {
str += "\n" + books[i];
}
return str + '\n';
}
- 基本方法
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public void setBooks(Book[] books) {
this.books = books;
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
- 自定义设置方法
public Book[] getBooks() {
return books;
}
public Book getBooks(int pos) {
return books[pos];
}
public void setBooks(Book book, int pos) {
this.books[pos] = book;
}
1. 通过输入1 / 2 确定身份
- 先看代码:
- (这里我并没有设置完全退出系统(并且一个人在系统中,可以一直操作,直到退出),而是让之后的人继续进入,并且书架的书不变)
public class Main {
public static User judge(int role, String name) {
return role == 1 ? new Admin(name) : new Normal(name);
}
public static void main(String[] args) {
BookList bookList = new BookList();
while(true) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入你的名字:>");
String name = scanner.nextLine();
System.out.println("1. 管理员\n2. 普通用户");
System.out.print("请输入你的身份:>");
int role = scanner.nextInt();
User user = judge(role, name);
user.menu(bookList);
}
}
}
public abstract class User {
protected String name;
public abstract void menu(BookList bookList);
public User(String name) {
this.name = name;
}
}
public class Admin extends User {
//继承User
}
public class Normal extends User {
//继承User
}
-
User user = judge(role, name); user.menu(bookList);
-
public static User judge(int role, String name) { return role == 1 ? new Admin(name) : new Normal(name); }
-
这两段可能比较难理解
-
其实就是根据 输入
role
判断judge()
返回什么类型的实例化- 从而完成向上转型
- 从而根据实例化对象重写
menu()
方法 - 再用user重写后的
menu()
方法
2. 操作接口 - IOpera
public interface IOpera {
public void work(BookList bookList, String person);
//待重写方法
//这里的person指的是使用之人
}
2.1 根据上图实现接口重写方法
- 个人习惯一个类一个java文件
2.1.1 Add 添加书籍
- 这里我将【行输入】都放前面的原因
- 因为其他输入需要将多吃的回车先去掉,才能继续输入,不然接下来的行输入会错误的取到
'\n'
- 太过麻烦
- 因为其他输入需要将多吃的回车先去掉,才能继续输入,不然接下来的行输入会错误的取到
public class Add implements IOpera{
@Override
public void work(BookList bookList, String s) { //这里的s并没有实际意义,只是为了满足重写要求
//输入书的信息
Scanner scanner = new Scanner(System.in);
System.out.print("请输入要添加的书名:>");
String name = scanner.nextLine();
System.out.print("请输入这本书的作者:>");
String author = scanner.nextLine();
System.out.print("请输入这本书的类别:>");
String type = scanner.nextLine();
System.out.print("请输入这本书的价格:>");
Double price = scanner.nextDouble();
//拿到书
Book book = new Book(name, author, price, type);
//放入书架
bookList.setBooks(book, bookList.getNumber());
bookList.setNumber(bookList.getNumber() + 1);
//扩容机制
if(bookList.getCapacity() == bookList.getNumber()) {
bookList.setCapacity(bookList.getCapacity() + 5);
Book[] books = Arrays.copyOf(bookList.getBooks(), bookList.getCapacity());
bookList.setBooks(books);
}
System.out.println("添加成功!");
}
}
2.1.2 Del - 删除书籍
- **删除机制:**找出待删除的下标,将后面的东西往前挪动覆盖
- 必须使用从头往前挪
- 这里用到的查找下标方法来自接下来的
Search类
- 在这里还有一个功能,就是删的书被借走,应该找那个人要回
public class Del implements IOpera{
@Override
public void work(BookList bookList, String person) {
System.out.print("请输入你要删除的书:>");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int index = Search.search(bookList, name);
if(index != -1) {
if(bookList.getBooks(index).isState()) {
System.out.println("此书被借出,无法删除");
System.out.println("请找" + bookList.getBooks(index).getBorrower() + "要回此书");
return;
}
System.out.println("删除成功");
bookList.setBooks(null, index);
for (int i = index + 1; i < bookList.getNumber(); i++) {
bookList.setBooks(bookList.getBooks(i), i - 1);
bookList.setBooks(null, i);
}
bookList.setNumber(bookList.getNumber() - 1);
}else {
System.out.println("找不到你要删除的书");
}
}
}
4.1.3 Search - 查看书籍
- 遍历找书即可
public class Search implements IOpera{
public static int search(BookList bookList, String name) {
for (int i = 0; i < bookList.getNumber(); i++) {
if(bookList.getBooks()[i].getName().equals(name)) {
return i;
}
}
return -1;
}
@Override
public void work(BookList bookList, String person) {
System.out.print("请输入你想查询的书:>");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int index = search(bookList, name);
if(index != -1) {
System.out.println("找到了");
System.out.println(bookList.getBooks()[index]);
}else {
System.out.println("未能找到");
}
}
}
2.1.4 Show - 展示书单
- 打印书架
bookList
即可
public class Show implements IOpera{
@Override
public void work(BookList bookList, String person) {
System.out.println(bookList);
System.out.println("展示成功");
}
}
2.1.5 Borrow - 借书
- 书只有一本,看有无被借走
- 无权知晓谁就走的
public class Borrow implements IOpera{
@Override
public void work(BookList bookList, String person) {
System.out.print("请输入你要借的书:>");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int index = Search.search(bookList, name);
if(index != -1) {
if(bookList.getBooks(index).isState()) {
System.out.println(name + "已被借走");
}else {
System.out.println("借阅成功");
bookList.getBooks(index).setState(true);
bookList.getBooks(index).setBorrower(person);
}
}else {
System.out.println("你要的书这里找不到");
}
}
}
2.1.6 Return - 还书
- 归还的书应该是这书架的
- 如果找不到这本书,那么就不是原书架的
- 如果这本书没被借走,那么就不是原书架的
public class Return implements IOpera{
@Override
public void work(BookList bookList, String person) {
System.out.print("请输入你要归还的书:>");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int index = Search.search(bookList, name);
if(index != -1 && bookList.getBooks(index).isState()) {
System.out.println("归还成功");
bookList.getBooks(index).setState(false);
}else {
System.out.println("此书并不是你在此处借的");
}
}
}
2.1.7 Exit - 退出系统
- 我取消了
exit(0)
退出的想法,因为我想继续有人进入系统
public class Exit implements IOpera{
@Override
public void work(BookList bookList, String person) {
System.out.println("退出成功");
//System.exit(0) 为正常退出执行!就是直接不执行了,而不是跳到末尾,也不是直接此方法结束,是整个程序结束
}
}
3. Admin 管理员视角的menu()方法
知识背景:数组向上转型技巧 --> 各元素不同的向上转型
- 这是管理员类
public class Admin extends User{
public Admin(String name) {
super(name);//传参不是给自己,而是给父类构造
}
//不同下标的元素,实现了不同的向上转型,重写了不同的方法
private IOpera[] iOperas = {
new Exit(),
new Add(),
new Del(),
new Search(),
new Show()
};
}
@Override
public void menu(BookList bookList) {
int choice = 0;
do{
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.print("请输入你的选择:>");
Scanner scanner = new Scanner(System.in);
choice = scanner.nextInt();
iOperas[choice].work(bookList, this.name);
//调用被不同向上转型的不同引用的work()方法
}while(!(iOperas[choice] instanceof Exit));
//只要改下标对应元素是Exit实例化的,就退出。
}
4. Normal 普通用户视角的menu()方法
- 同理:
public class Normal extends User{
public Normal(String name) {
super(name);
}
private IOpera[] iOperas = {
new Exit(),
new Search(),
new Borrow(),
new Return()
};
@Override
public void menu(BookList bookList) {
int choice = 0;
do {
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.print("请输入你的选择:>");
Scanner scanner = new Scanner(System.in);
choice = scanner.nextInt();
iOperas[choice].work(bookList, this.name);
}while(!(iOperas[choice] instanceof Exit));
}
}
测试
- 一定要在main方法所在文件才能运行哦
在这里插入图片描述
文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆!这是我的代码仓库!(在马拉圈的23.1里)代码仓库 图书管理代码具体位置