前言
本人的技术笔记优先发布在个人站点longyxblg.cn
本文主要是通过 Java 语言进行手写一个简易的图书管理系统,不采用数据结构。主要完成的是一个简易框架的搭建,业务逻辑仅满足可用并不严谨。
梳理框架
这个简易图书管理系统设计为3个对象互相交互, 分别为:用户、书架、书。 整个系统的维护实际上是对书架进行操作。
用户分为普通用户和管理员用户,区别在于对书架操作的权限不同。
书包含书名,作者名,价格,是否借出这四个属性。
书架用于管理书籍。
用户类
新建一个 User 类, 用户分为普通用户和管理员用户, 这两个用户才是去执行业务的类,所以 User 类设计为一个抽象类。
java
package Demo1;
public abstract class User {
// 不需要 User 类去执行业务
protected String name;
public User() {
}
public User(String name) {
this.name = name;
}
}
java
package Demo1;
public class NormalUser extends User {
public NormalUser(String name) {
super(name);
}
public NormalUser() {
}
}
java
package Demo1;
public class AdminUser extends User{
public AdminUser(String name) {
super(name);
}
public AdminUser() {
}
}
此时,需要一个登录方法 login() , 判断用户登录后是普通用户还是管理员。这个方法应不需要依赖对象就可以调用,所以应该被 static 修饰。
java
public static User login(){
// 登录方法不需要借助依赖对象进行调用
System.out.println("请输入您的用户名:");
Scanner scanner = new Scanner(System.in);
String userName = scanner.nextLine();
System.out.println("请选择您的身份:");
System.out.println("1.普通用户 2.管理员");
int choice = scanner.nextInt();
if(choice == 1){
// 主要目的是设计一个框架,业务并没有处理的很严谨
return new NormalUser(userName);
}else {
return new AdminUser(userName);
}
}
然后根据用户类型,会有不同的操作菜单。定义一个 menu() 方法。这个方法在 User 类中是一个抽象方法,具体的实现在 AdminUser 和 NormalUser 类中。
java
public abstract int menu();
在管理员用户中,设计可以进行以下操作:
-
增加图书
-
删除图书
-
修改图书
-
查找图书
-
退出系统
java
package Demo1;
import java.util.Scanner;
public class AdminUser extends User{
public AdminUser(String name) {
super(name);
}
public AdminUser() {
}
@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.退出系统");
Scanner scanner = new Scanner(System.in);
// 通过返回的数值来确定执行什么操作
int choice = scanner.nextInt();
return choice;
}
}
普通用户类设计为可以进行以下操作:
-
展示图书(展示当前书架所有的图书)
-
借阅图书
-
归还图书
-
查找图书
-
退出系统
java
package Demo1;
import java.util.Scanner;
public class NormalUser extends User {
public NormalUser(String name) {
super(name);
}
public NormalUser() {
}
@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.退出系统");
Scanner scanner = new Scanner(System.in);
// 通过返回的数值来确定执行什么操作
int choice = scanner.nextInt();
return choice;
}
}
测试一下是否能正常运行
java
User user = User.login();
user.menu();


用户类的设计暂时到这里
书本类
书本类的设计较为简单,但是书本的成员变量需要将其封装起来。使用 private 修饰,想要修改查看就通过 get 、 set 方法。
java
package Demo1;
public class Book {
private String book_Name;
private String author;
private double price;
// 判断是否借出
// true 表示借出
// false 表示未借出
private boolean isBorrowed;
public Book() {
}
public Book(String book_Name, String author, double price) {
// 每个 Book 类型对象实例化后默认都是未被借出的
// boolean 类型不初始化的情况下默认值就是 false
this.book_Name = book_Name;
this.author = author;
this.price = price;
}
public String getBook_Name() {
return book_Name;
}
public String getAuthor() {
return author;
}
public double getPrice() {
return price;
}
public void setBook_Name(String book_Name) {
this.book_Name = book_Name;
}
public void setAuthor(String author) {
this.author = author;
}
public void setPrice(double price) {
this.price = price;
}
public void setBorrowed(boolean borrowed) {
this.isBorrowed = borrowed;
}
}
构造方法中不给 isBorrowed 赋值是因为每个 Book 类型对象实例化后默认都是未被借出的,即
isBorrowed 的值是 false 。而 boolean 类型不初始化的情况下默认值就是 false 。
书本类的设计暂时到此。
书架类
用于存放书本,采用数组进行存放
java
package Demo1;
public class BookList {
// 这个简易图书管理系统的维护实际上就是对 BookList 实例化的对象进行操作
// 默认给一个可以存放 10 个 Book 类型对象的数组
Book[] booklist = new Book[10];
public BookList(){
// 在实例化这个书架时,默认里面放三本书
booklist[0] = new Book("《三体》","刘慈欣",29.99);
booklist[1] = new Book("《天父地母》","王晋康",19.99);
booklist[2] = new Book("《逃出母宇宙》","王晋康",9.99);
}
}
书架类的设计暂时到这里。
IOperation
用户做的所有操作都通过实现这个接口完成
java
package Demo1;
public interface IOperation {
void work(Book[] books);
}
FindOperation 类
通过这个类来实现用户操作中的查找图书
java
package Demo2;
import Demo1.Book;
import Demo1.IOperation;
public class FindOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("查找图书");
}
}
AddOperation 类
通过这个类实现管理员用户操作中的新增图书
java
package Demo2;
import Demo1.Book;
import Demo1.IOperation;
public class AddOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("新增图书");
}
}
BorrowOperation 类
通过这个类来实现普通用户操作中的借阅图书
java
package Demo2;
import Demo1.Book;
import Demo1.IOperation;
public class BorrowOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("借阅图书");
}
}
DelOperation 类
通过这个类来实现管理员用户操作中的删除图书
java
package Demo2;
import Demo1.Book;
import Demo1.IOperation;
public class DelOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("删除图书");
}
}
EditOperation 类
通过这个类来实现管理员用户操作中的修改图书
java
package Demo2;
import Demo1.Book;
import Demo1.IOperation;
public class EditOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("修改图书");
}
}
ReturnOperation 类
通过这个类来实现普通用户操作中的归还图书
java
package Demo2;
import Demo1.Book;
import Demo1.IOperation;
public class ReturnOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("归还图书");
}
}
ShowOperation 类
通过这个类来实现普通用户操作中的展示所有图书操作
java
package Demo2;
import Demo1.Book;
import Demo1.IOperation;
public class ShowOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("归还所有图书");
}
}
成员类的修改
在用户类中新增 IOperation 类型的数组,并实现对应的 get 方法
java
package Demo1;
import java.util.Scanner;
public abstract class User {
// 不需要 User 类去执行业务
protected String name;
// 多态的使用
IOperation[] iOperations;
public User() {
}
public User(String name) {
this.name = name;
}
public static User login(){
// 登录方法不需要借助依赖对象进行调用
System.out.println("请输入您的用户名:");
Scanner scanner = new Scanner(System.in);
String userName = scanner.nextLine();
System.out.println("请选择您的身份:");
System.out.println("1.普通用户 2.管理员");
int choice = scanner.nextInt();
if(choice == 1){
// 主要目的是设计一个框架,业务并没有处理的很严谨
return new NormalUser(userName);
}else {
return new AdminUser(userName);
}
}
// 根据不同用户类型显示不同的菜单
public abstract int menu();
public IOperation[] getiOperations() {
return iOperations;
}
}
java
package Demo1;
import Demo2.*;
import java.util.Scanner;
public class NormalUser extends User {
IOperation[] iOperations = {new EixtOperation(),new ShowOperation(),new BorrowOperation(), new ReturnOperation(),new FindOperation()};
public NormalUser(String name) {
super(name);
}
public NormalUser() {
}
@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.退出系统");
Scanner scanner = new Scanner(System.in);
// 通过返回的数值来确定执行什么操作
int choice = scanner.nextInt();
return choice;
}
@Override
public IOperation[] getiOperations() {
return this.iOperations;
}
}
java
package Demo1;
import Demo2.*;
import java.util.Scanner;
public class NormalUser extends User {
IOperation[] iOperations = {new EixtOperation(),new ShowOperation(),new BorrowOperation(), new ReturnOperation(),new FindOperation()};
public NormalUser(String name) {
super(name);
}
public NormalUser() {
}
@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.退出系统");
Scanner scanner = new Scanner(System.in);
// 通过返回的数值来确定执行什么操作
int choice = scanner.nextInt();
return choice;
}
@Override
public IOperation[] getiOperations() {
return this.iOperations;
}
}
java
package Demo1;
import Demo2.*;
import java.util.Scanner;
public class AdminUser extends User{
IOperation[] iOperations = {new EixtOperation(),new AddOperation(),new DelOperation(),new EditOperation() , new FindOperation()};
public AdminUser(String name) {
super(name);
}
public AdminUser() {
}
@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.退出系统");
Scanner scanner = new Scanner(System.in);
// 通过返回的数值来确定执行什么操作
int choice = scanner.nextInt();
return choice;
}
@Override
public IOperation[] getiOperations() {
return this.iOperations;
}
}
接下来就来测试是否能够成功调用对应的方法
java
package Demo2;
import Demo1.BookList;
import Demo1.IOperation;
import Demo1.User;
public class Test {
public static void main(String[] args) {
User user = User.login();
BookList bookList = new BookList();
while(true){
int choice = user.menu();
IOperation[] iOperations = user.getiOperations();
iOperations[choice].work(bookList.getBooklist());
}
}


可以看到确实是能达到预期中的效果,接下来就是具体实现对应的方法。
FindOperation 方法的实现
java
public void work(Book[] books) {
System.out.println("查找图书");
}
逻辑是通过书名来进行查找,遍历整个 books 。先给 Book 类重写一个 toString 方法。
java
@Override
public String toString() {
return "Book{" +
"book_Name='" + book_Name + '\'' +
", author='" + author + '\'' +
", price=" + price +
(isBorrowed ? ",已借出" : ",未借出") +
'}';
}
测试一下
java
Book book = new Book("《三体》","刘慈欣",29.99);
System.out.println(book);

此时给 BookList 类中新增一个属性 usedSize 表示这个数组使用的空间长度,同时为这个属性写一个 get 方法。
java
package Demo1;
public class BookList {
// 这个简易图书管理系统的维护实际上就是对 BookList 实例化的对象进行操作
// 默认给一个可以存放 10 个 Book 类型对象的数组
Book[] booklist = new Book[10];
int usedSize = 3;
public BookList(){
// 在实例化这个书架时,默认里面放三本书
booklist[0] = new Book("《三体》","刘慈欣",29.99);
booklist[1] = new Book("《天父地母》","王晋康",19.99);
booklist[2] = new Book("《逃出母宇宙》","王晋康",9.99);
}
public Book[] getBooklist() {
return booklist;
}
public int getUsedSize() {
return usedSize;
}
}
逻辑是遍历数组,通过 name 这个成员来查找图书。
java
package Demo2;
import Demo1.Book;
import Demo1.BookList;
import Demo1.IOperation;
import java.util.Scanner;
public class FindOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("请输入你要查找的书籍名称:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
if(name.equals(bookList.getBooklist()[i].getBook_Name())){
// bookList.getBooklist() 拿到存放 book 的数组
// bookList.getBooklist()[i] 拿到下标为 i 的 book 对象
// 再用 getBook_Name() 拿到书名
System.out.println("找到了");
System.out.println(bookList.getBooklist()[i]);
return;
}
}
// 出来说明没找到
System.out.println("当前没有存放你想要查找的书籍");
}
}
测试一下


ShowOperation 方法的实现
遍历数组,将每个对象都打印出来即可
java
package Demo2;
import Demo1.BookList;
import Demo1.IOperation;
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++) {
// bookList.getBooklist() 拿到存放 book 的数组
// bookList.getBooklist()[i] 拿到下标为 i 的 book 对象
System.out.println(bookList.getBooklist()[i]);
}
}
}

BorrowOperation 方法的实现
给 Book 类中新增一个获取借阅状态的方法
java
public boolean isBorrowed() {
return isBorrowed;
}
借出书籍也是根据书籍名称来查找,找到了判断借出状态,如果是未借出状态就修改借出状态。否则告知已借出。没找到也告知。
java
package Demo2;
import Demo1.BookList;
import Demo1.IOperation;
import java.util.Scanner;
public class BorrowOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("请输入你要借阅的书籍名称:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
if (name.equals(bookList.getBooklist()[i].getBook_Name())) {
// bookList.getBooklist() 拿到存放 book 的数组
// bookList.getBooklist()[i] 拿到下标为 i 的 book 对象
// 再用 isBorrowed() 拿到借阅状态
if(bookList.getBooklist()[i].isBorrowed()){
System.out.println("该书已借出");
}else {
System.out.println("借阅成功!");
bookList.getBooklist()[i].setBorrowed(true);
}
return;
}
}
// 出来说明没找到
System.out.println("当前没有存放你需要的书籍");
}
}
测试一下

ReturnOperation 方法的实现
根据书籍名称来查找,找到了判断借出状态,如果是已借出状态就修改借出状态。否则告知未借出。没找到也告知。
java
package Demo2;
import Demo1.BookList;
import Demo1.IOperation;
import java.util.Scanner;
public class ReturnOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("请输入你要归还的书籍名称:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
if (name.equals(bookList.getBooklist()[i].getBook_Name())) {
// bookList.getBooklist() 拿到存放 book 的数组
// bookList.getBooklist()[i] 拿到下标为 i 的 book 对象
// 再用 isBorrowed() 拿到借阅状态
if(bookList.getBooklist()[i].isBorrowed()){
System.out.println("归还成功!");
bookList.getBooklist()[i].setBorrowed(false);
}else {
System.out.println("该书未借出");
}
return;
}
}
// 出来说明没找到
System.out.println("当前系统没有存放该书籍");
}
}
测试

EixtOperation 方法的实现
直接退出就可以了
java
package Demo2;
import Demo1.BookList;
import Demo1.IOperation;
public class EixtOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("退出系统");
System.exit(0);
}
}
测试

AddOperation 方法的实现
采用尾插的方式添加书籍,直接在 usedSize 处插入即可,插入后要让 usedSize + 1。在 BookList 类中添加一个 set 方法。
java
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
在添加的时候要判断书架还能不能放得下
java
package Demo2;
import Demo1.Book;
import Demo1.BookList;
import Demo1.IOperation;
import java.util.Scanner;
public class AddOperation implements IOperation {
@Override
public void work(BookList bookList) {
if(bookList.getUsedSize() == 10){
System.out.println("当前书架已满!");
return;
}
System.out.println("请输入你要新增的书籍名称");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("请输入你要新增的书籍作者名");
String author = scanner.nextLine();
System.out.println("请输入你要新增的书籍价格");
double price = scanner.nextDouble();
Book newBook = new Book(name,author,price);
int currentSize = bookList.getUsedSize();
// 尾插进去
bookList.getBooklist()[currentSize] = newBook;
// 插入后让 usedSize + 1
bookList.setUsedSize(++currentSize);
System.out.println("插入成功!");
}
}
给 AdminUser 类也加一个展示图书的方法方便查看
java
IOperation[] iOperations = {new EixtOperation(),new AddOperation(),new DelOperation(),new EditOperation() , new FindOperation(),new ShowOperation()};
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("5.展示图书:");
System.out.println("0.退出系统");
Scanner scanner = new Scanner(System.in);
// 通过返回的数值来确定执行什么操作
int choice = scanner.nextInt();
return choice;
}
java
package Demo2;
import Demo1.Book;
import Demo1.BookList;
import Demo1.IOperation;
import java.util.Scanner;
public class AddOperation implements IOperation {
@Override
public void work(BookList bookList) {
if(bookList.getUsedSize() == 10){
System.out.println("当前书架已满!");
return;
}
System.out.println("请输入你要新增的书籍名称");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("请输入你要新增的书籍作者名");
String author = scanner.nextLine();
System.out.println("请输入你要新增的书籍价格");
double price = scanner.nextDouble();
Book newBook = new Book(name,author,price);
int currentSize = bookList.getUsedSize();
// 尾插进去
bookList.getBooklist()[currentSize] = newBook;
// 插入后让 usedSize + 1
bookList.setUsedSize(++currentSize);
System.out.println("插入成功!");
}
}
测试

EditOperation 方法的实现
也是通过 name 查找要修改的对象,查找到了再进行修改
java
package Demo2;
import Demo1.BookList;
import Demo1.IOperation;
import java.util.Scanner;
public class EditOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("请输入你要修改的书籍名称:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
if(name.equals(bookList.getBooklist()[i].getBook_Name())){
// bookList.getBooklist() 拿到存放 book 的数组
// bookList.getBooklist()[i] 拿到下标为 i 的 book 对象
System.out.println("请输入修改后的书籍名称");
String book_name = scanner.nextLine();
System.out.println("请输入修改后的作者名");
String author = scanner.nextLine();
System.out.println("请输入修改后的价格");
double price = scanner.nextDouble();
bookList.getBooklist()[i].setBook_Name(book_name);
bookList.getBooklist()[i].setAuthor(author);
bookList.getBooklist()[i].setPrice(price);
System.out.println("修改成功!");
return;
}
}
// 出来说明没找到
System.out.println("当前没有存放你想要修改的书籍");
}
}
测试

DelOperation 方法的实现
也是通过 name 查找要删除的数据, 找到了将这个位置的后的数据整体向前移动一格, 然后让 usedSize - 1
java
package Demo2;
import Demo1.Book;
import Demo1.BookList;
import Demo1.IOperation;
import java.util.Scanner;
public class DelOperation implements IOperation {
@Override
public void work(BookList bookList) {
if(bookList.getUsedSize() == 0){
System.out.println("当前书架已空!");
return;
}
System.out.println("请输入你要删除的书籍名称:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
if(name.equals(bookList.getBooklist()[i].getBook_Name())){
// bookList.getBooklist() 拿到存放 book 的数组
// bookList.getBooklist()[i] 拿到下标为 i 的 book 对象
for (int j = i; j < currentSize - 1; j++) {
// 让删除的位置后的数据整体向前移动一位进行覆盖
bookList.getBooklist()[j] = bookList.getBooklist()[j + 1];
}
// 删除后让 usedSize - 1
bookList.setUsedSize(--currentSize);
System.out.println("删除完成!");
return;
}
}
// 出来说明没找到
System.out.println("当前没有存放你想要删除的书籍");
}
}
测试

这是测试用的代码
java
User user = User.login();
BookList bookList = new BookList();
while(true){
int choice = user.menu();
IOperation[] iOperations = user.getiOperations();
iOperations[choice].work(bookList);
}
到底为止,这个简易的图书管理系统就完成了。本文旨在完成一个简单的逻辑,业务处理只是可用即可并不严谨(例如没有验证输入合法性等)。