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里)代码仓库 图书管理代码具体位置