目录
前言
一. 图书管理系统的核心
二. 图书管理系统基本框架
2.1 book包
2.1.1 Book(书籍类)
2.1.2 Booklist (书架类)
2.2 user包
2.2.1 User类
2.2.2 Administrator(管理员类)
2.2.3 Visitor(用户类)
2.3 图书管理系统操作菜单
管理员菜单
用户菜单
2.4 operation(操作包)
三. 实现服务
3.1 显示所有书籍
3.2 查找书籍
3.3 退出系统
3.4 增加书籍
3.5 删除书籍
3.6 借阅书籍
3.7 归还书籍
四. 总代码
结语
前言
相信大家都有去过图书馆吧,那么在借阅图书和归还的时候,都有一个系统来记录并操作这些过程,所以今天就带着大家利用之前的所学知识来简单实现一下图书管理系统的基本逻辑构造
一. 图书管理系统的核心
图书管理系统的核心包括三个部分:书籍的信息(书本属性)、操作书籍的人(管理员和读者)、 对书籍的操作(借阅、归还)
所以在这里我们分别创建3个包 book、operation、user 来实现各个部分的操作:
二. 图书管理系统基本框架
2.1 book包
我们在book这个包中创建2个类:Book、Booklist,Book用来描述书籍的基本信息,Booklist充当书架,里面用来记录书架中书籍的信息。
2.1.1 Book(书籍类)
首先在Book中我们要创建变量来记录书籍的基本信息:
private String name; //书名
private String author; //作者
private int price; //价格
private String type; //书籍类型
private boolean isborrow; //是否被借出
并且这里的书籍基本信息,我们是用private访问修饰限定符修饰变量的,其他类想要直接访问是访问不了的,所以这里需要我们创建方法间接访问。
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 isIsborrow() {
return isborrow;
}
public void setIsborrow(boolean isborrow) {
this.isborrow = isborrow;
}
接下来我们来写Book类的构造方法:
那么当我们每次新增一本书的时候 ,该书籍默认就是未借出的状态,默认初始值就是false,所以不需要在构造方法中进行初始化
public Book(String name, String author, int price, String type) {
//初始化书的属性
this.name = name;
this.author = author;
this.price = price;
this.type = type;
}
这时候书籍的信息属性都能够被记录了,那么我们想看看这些书籍的信息该怎么办呢?没错打印出来,此时我们需要对 ToString 方法进行重写:
2.1.2 Booklist (书架类)
能够记录书籍信息的Book类创建完成后,我们来创建一个书架类(Booklist),书架类的作用就是能够存放每一本书,并且记录每一本书的借阅状态。
private Book [] books;//表示书架可以存放10本书
private int usedbooks;//表示books数组中存放了几本书
那么我们依然需要通过间接访问才能访问书架中的基本信息,需要自己提供方法间接访问:
public int getUsedbooks() {
return usedbooks;//返回有效书本数量
}
public void setUsedbooks(int usedbooks) {
this.usedbooks = usedbooks;//更改有效书本数量
}
public Book getbook(int pos){
return books[pos]; //返回书架中 第pos本书
}
public void setBooks(int pos,Book book){
this.books[pos]=book; //更改书架中的书
}
那么我们还是写一下Booklist类的构造方法,默认书架中已经存放了书籍:
public BookList() {
this.books = new Book [10]; //默认创建存放10本书大小的数组
this.books[0]=new Book("三国演义","罗贯中",20,"四大名著");
this.books[1]=new Book("西游记","吴承恩",22,"四大名著");
this.books[2]=new Book("红楼梦","曹雪芹",24,"四大名著");
this.books[3]=new Book("水浒传","施耐庵",26,"四大名著");
this.usedbooks=4;//初始化有效书本数量为4本
}
那么在book这个包的操作就告一段落,后续随着思路的深入再进行补充~
2.2 user包
在user包中我们新建三个类来描述管理员和用户,那么管理员和用户也是拥有相同属性的,而第三个类User,我们就定义成抽象类,让管理员类与用户类去继承,这样就可以省略一些重复的代码啦
2.2.1 User类
那么管理员与用户共同拥有的特征就是都有名字,那么我们就在User类中定义一个名字属性的变量,并且通过构造方法初始化 管理员 或 用户 的名称:
public abstract class User {
public String name; //名字
public User(String name) {
this.name = name; //初始化名称
}
}
2.2.2 Administrator(管理员类)
因为我们的管理员类继承了User类,所以需要在构造方法中调用父类的构造方法:
public class Administrator extends User{
public Administrator(String name) {
super(name);//通过父类初始化管理员名称
}
}
2.2.3 Visitor(用户类)
同理用户类也继承了User类,所以也需要构造方法调用父类的构造方法:
public class Visitor extends User{
public Visitor(String name) {
super(name); //通过父类初始化用户名称
}
}
那么书籍的属性和操作者的基本框架我们已经实现了,接下来该实现一下图书管理系统的功能了~
2.3 图书管理系统操作菜单
管理员菜单
1.查找图书
2.新增图书
3.删除图书
4.显示图书
0.退出系统
用户菜单
1.查找图书
2.借阅图书
3.归还图书
0.退出系统
接下来,我们就针对这些功能创建一个包,实现这些功能。
2.4 operation(操作包)
在这个包中我们去实现上述描述的相关操作,接着我们创建一个接口来实现多态,从而降低代码的复杂度
operate接口:
public interface Operate { //服务接口
void work(BookList books);
//功能的实现我们都要利用到书架,所以这里参数给定一个书架对象
}
接下来我们创建实现各个功能的类:
Addbook类:(新增书籍)
public class Addbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("增加书籍...");
}
}
Borrowbook类:(借阅书籍)
public class Borrowbook implements Operate {
@Override
public void work(BookList books) {
System.out.println("借阅书籍....");
}
}
Deletebook类:(删除书籍)
public class Deletebook implements Operate{
@Override
public void work(BookList books) {
System.out.println("删除书籍...");
}
}
Exitbook类:(退出系统)
public class Exitbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("退出系统.....");
}
}
Findbook类:(查阅书籍)
public class Findbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("查找书籍....");
]
}
Returnbook类:(归还书籍)
public class Retuenbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("归还书籍....");
Showbook类:(显示书籍)
public class Showbook implements Operate {
@Override
public void work(BookList books) {
System.out.println("显示书籍....");
}
}
接下来就要慢慢的去将每个类的功能具体的实现,并且将每个类联系起来运作图书管理系统。
既然知道了管理员和用户的菜单后,我们就分别给管理员和用户添加一下菜单:
在Administrator类添加管理员菜单:
public void menu() {
System.out.println("欢迎 "+this.name+" 管理员来到图书管理系统");
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("<<******************************************>>");
}
在Visitor类中添加用户菜单:
public void menu(){
System.out.println("欢迎 "+this.name+" 读者来到图书管理系统");
System.out.println("<<***************游客读者菜单*************>>");
System.out.println("1. 查找图书 ");
System.out.println("2. 借阅图书 ");
System.out.println("3. 归还图书 ");
System.out.println("0. 退出系统 ");
System.out.println("<<**************************************>>");
}
那么我们现在创建一个Main类,在类中写上我们的main方法实现一下基本逻辑:
public class Main {
public static User login(){ //登录系统过程
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你的名字:");
String name = scanner.nextLine();
System.out.println("请输入你要登入的帐号:1.管理员登录 -----> 2.游客登录 ----->");
int choice=scanner.nextInt();
if(choice==1){
return new Administrator(name); //如果选择了1,就实例化一个管理员对象,并返回
}else{
return new Visitor(name); //如果选择了2,就实例化一个用户对象,并返回
}
//此时的返回值我们不能确定返回的是管理员对象还是用户对象,所以这里用向上转型返回User类型的对象
}
public static void main(String[] args) {
User user=login(); //进入登录系统
user.menu(); //打印菜单
}
}
但是此时login方法的返回对象我们使用User类型的对象进行接收的,此时我们是不能使用user.menu()的,那么该怎么办呢?我们之前将User抽象出来作为管理员类和用户类的父类,那么此时我们在User类中写一个menu()方法就可以实现多态,打印菜单啦~
public abstract class User {
public String name; //用户名称
public User(String name) {
this.name = name; //初始化用户名称
}
public abstract int menu(); //抽象方法实现多态,打印菜单
}
那么此时只需要将子类做出相应的改动,改变成重写的形式就可以了:
这就实现了打印菜单的功能,但是光打印选择不了功能可不行呀,所以我们要在菜单中加上一个选择功能:
@Override
public int menu() {
System.out.println("欢迎 "+this.name+" 管理员来到图书管理系统");
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("<<******************************************>>");
//选择功能
Scanner scanner=new Scanner(System.in);
System.out.println("请选择您需要的服务:-->>");
int choice=scanner.nextInt();
return choice;
}
通过输入标号来选择我们想要的服务,那么我们应该返回这个标号,所以menu()方法的返回值也要改成 int 类型,Visitor类的menu()方法也是同理。
那么能够选择服务后,我们应该根据对象(管理员或用户)选择该调用哪一个菜单方法:
Administrator(管理员类):
public Administrator(String name) {
super(name);//通过父类初始化管理员名称
this.operate=new Operate[]{ //创建 管理员账户提供的服务
new Exitbook(),
new Findbook(),
new Addbook(),
new Deletebook(),
new Showbook()
};
}
Visitor(用户类):
public class Visitor extends User{
public Visitor(String name) {
super(name); //通过父类初始化用户名称
this.operate=new Operate[]{ //创建 游客账户提供的服务
new Exitbook(),
new Findbook(),
new Borrowbook(),
new Retuenbook()
};
}
那么当我们分别在它们的构造方法中创建一个Operate类型的数组后,里面存放Operate接口实现的方法,那么在new一个管理员对象或者用户对象时,系统就会为这个数组分配内存:
那么我们需要在User类中加上这么一段代码利用动态绑定调用管理员菜单中的方法还是调用用户菜单中的方法:
public Operate []operate; //创建服务数组,子类通过数组下标调用 各个服务
public void Dooperate(int choice,BookList books){
this.operate[choice].work(books); //调用 游客/管理员 所选择的服务
}
this.operate[ choice ]就是我们new的那个对象中构造方法中下标为 choice 的那个类,而后面的 .work(books)就是调用的对应类的work方法。
那么现在我们在main方法中打印菜单的时候就需要有个变量来接收选择的服务啦,再通过new对应的对象调用上面写的 Dooperate方法调用所选择的服务。
public static void main(String[] args) {
BookList bookList=new BookList(); //实例化书架
User user=login(); //进入登录系统
while(true) {
int chioce = user.menu(); //接收选择服务的选项
user.Dooperate(chioce, bookList); //调用 游客/管理员 提供的服务
}
}
而为了实现用户输入0时才退出系统,所以这里的while循环我们设置为死循环。此时基本框架就搭建完成啦~
我们来看看测试效果:
那么我们来画图分析一下运行的过程:
1. 通过主函数调用login方法:
2. 通过login方法返回的对象调用该对象类中的menu()方法
3. 最后通过调用user.Dooperate方法一步一步实现所选择的服务
三. 实现服务
3.1 显示所有书籍
那么在实现显示书籍功能之前,我们应该在Booklist类中写一个方法让Showbook类中的work方法能够通过数组下标打印书籍的信息:
public Book getbook(int pos){
return this.books[pos]; //返回书架中 第pos本书
}
接下来我们就可以实现显示书籍这个服务啦~
在Showbook类中实现:
public class Showbook implements Operate {
@Override
public void work(BookList books) {
System.out.println("显示书籍....");
int count=books.getUsedbooks();
for(int i=0;i<count;i++) {
//通过循环遍历数组;调用books.getbook(i)方法获取指定的书籍对象
System.out.println(books.getbook(i).toString());
}
System.out.println();
}
}
3.2 查找书籍
查找书籍的过程与显示所有书籍相似,也是通过循环遍历数组,利用equal()方法进行对比,实现服务。
在Findbook类中实现:
public class Findbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("查找书籍....");
Scanner scanner=new Scanner(System.in);
System.out.print("请输入要查找书籍的名字:-->");
String name=scanner.nextLine();
int count=books.getUsedbooks();
for(int i=0;i<count;i++)
{
Book book=books.getbook(i);
if(book.getName().equals(name)){
System.out.println("找到了,书本内容如下:");
System.out.println(book);
System.out.println();
return;
}
}
System.out.println("很抱歉,没有查找到你要查找的书籍");
System.out.println("后续会尽快联系管理员添加~");
System.out.println();
}
}
3.3 退出系统
在Exitbook类中实现:
public class Exitbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("退出系统.....");
int count=books.getUsedbooks();
for(int i=0;i<count;i++)
{
books.setBooks(i,null); //
}
books.setUsedbooks(0); //将有效书籍数量 制为空
System.exit(0);
}
}
书架中存放的书籍都是对象,那么在退出系统之前我们应该将书籍对象都进行回收,避免发生内存泄漏,并且将书架中的书本数量变成0,最后在结尾加上 System.exit(0); 就可以结束程序,退出系统了。
3.4 增加书籍
在增加书籍之前,我们应该先判断这个书籍是否已经在书架中存放,如果书架中没有那么就添加到书架中
在Addbook类中实现:
public class Addbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("增加书籍...");
int count=books.getUsedbooks();
Scanner scanner=new Scanner(System.in);
System.out.print("请输入新添加的书名:--->");
String name=scanner.nextLine();
System.out.print("请输入新添加书籍的作者:--->");
String author=scanner.nextLine();
System.out.print("请输入书籍的价格:--->");
int price=scanner.nextInt();
scanner.nextLine();
System.out.print("请输入书籍的类型:--->");
String type=scanner.nextLine();
for(int i=0;i<count;i++) {
if(books.getbook(i).getName().equals(name)){
System.out.println("该书籍已经存在了,不需要添加-----");
System.out.println();
return ;
}
}
Book book=new Book(name,author,price,type);
books.setBooks(count,book);
System.out.println("添加成功---");
books.setUsedbooks(count+1);
System.out.println();
}
}
那么在Booklist类中我们就要提供一个方法用来新增书籍:
public void setBooks(int pos,Book book){
this.books[pos]=book; //更改书架中的书
}
3.5 删除书籍
在删除书籍中我们有两个点需要注意:当我们删除了某本书籍后,需要将该书籍后面的书籍往前移动,并且将移动完最后的那个空间进行回收,并且更改书架中书籍的数量
在Deletebook类中实现:
public class Deletebook implements Operate{
@Override
public void work(BookList books) {
System.out.println("删除书籍...");
System.out.print("请输入你要删除的书籍:--->");
Scanner scanner=new Scanner(System.in);
String name =scanner.nextLine();
int count=books.getUsedbooks();
int index=-1;
boolean flag=false;
for (int i = 0; i <count ; i++) {
if(books.getbook(i).getName().equals(name)){
index=i;
flag=true;
break;
}
}
if(flag==false) {
System.out.println("没有找到你要删除的书籍-----");
System.out.println();
return ;
}
if (books.getbook(index).isIsborrow()==true){
System.out.println("该书本已经被借出,暂时不能进行操作-----");
System.out.println();
return;
}else{
for(int j=index;j<count-1;j++)
{
books.setBooks(j,books.getbook(j+1));
}
System.out.println("删除成功------->");
books.setUsedbooks(count-1);
books.setBooks(count-1,null);
}
}
}
那么在删除书籍的时候为了实现将后面的书籍往前面移动,我们需要在Booklist类中调用setBooks方法来实现这个过程:
public void setBooks(int pos,Book book){
this.books[pos]=book; //更改书架中的书
}
3.6 借阅书籍
借阅书籍的时候我们应该判断该书籍是否在书架上存在,如果存在再判断该书籍是否被借出,如果没有被借出,那么就可以进行借阅
在Borrowbook类中实现:
ublic class Borrowbook implements Operate {
@Override
public void work(BookList books) {
System.out.println("借阅书籍....");
System.out.print("请输入你要借阅的图书:-->");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int count = books.getUsedbooks();
for (int i = 0; i < count; i++) {
if (books.getbook(i).getName().equals(name)) {
if (books.getbook(i).isIsborrow() == false) {
books.getbook(i).setIsborrow(true);
System.out.println("借阅成功---");
System.out.println(books.getbook(i));
System.out.println();
return;
}else{
System.out.println("这本书已经被借出,请等待读者归还后再进行借阅---");
System.out.println();
return ;
}
}
}
System.out.println("查找不到你要借阅的书籍,后续会联系管理员尽快上架!!!");
System.out.println();
}
}
这个时候我们需要在Book类中提供一个方法,返回当前书籍是否被借出的状态,并且还要提供一个方法改变书籍是否被借出的状态,在Book类中实现:
public boolean isIsborrow() {
return isborrow;
}
public void setIsborrow(boolean isborrow) {
this.isborrow = isborrow;
}
3.7 归还书籍
在归还之前我们需要判断一下这本书是否在书架上存在过,如果存在再进行判断这本书是否有被借出,如果有被借出则可以归还
在Returnbook类中实现:
public class Retuenbook implements Operate{
@Override
public void work(BookList books) {
System.out.println("归还书籍....");
System.out.print("请输入你要归还的图书:-->");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int count = books.getUsedbooks();
for (int i = 0; i < count; i++) {
if (books.getbook(i).getName().equals(name)) {
if (books.getbook(i).isIsborrow() == true) {
books.getbook(i).setIsborrow(false);
System.out.println("归还成功---欢迎再次借阅");
System.out.println(books.getbook(i));
System.out.println();
return;
}else{
System.out.println("这本书没有被借出,不需要归还---");
System.out.println();
return ;
}
}
}
System.out.println("查找不到你要归还的书籍,你可能是在其他图书馆借阅的书籍---");
System.out.println();
}
}
如果将书籍归还后我们需要将书籍是否借出的状态进行改变,在Book类中实现:
public boolean isIsborrow() {
return isborrow;
}
public void setIsborrow(boolean isborrow) {
this.isborrow = isborrow;
}
四. 总代码
Main类:
import book.BookList;
import user.Administrator;
import user.User;
import user.VipPerson;
import user.Visitor;
import java.util.Scanner;
public class Main {
public static User login(){ //登录系统过程
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你的名字:");
String name = scanner.nextLine();
System.out.println("请输入你要登入的帐号:1.管理员登录 -----> 2.游客登录 ----->");
int choice=scanner.nextInt();
if(choice==1){
return new Administrator(name); //如果选择了1,就创建一个管理员对象,并返回
}else if(choice==2){
return new Visitor(name); //如果选择了2,就创建一个游客对象,并返回
}else{
return new VipPerson(name);
}
//此时的返回值我们不能确定返回的是管理员对象还是用户对象,所以这里用向上转型返回User类型的对象
}
public static void main(String[] args) {
BookList bookList=new BookList(); //实例化书架
User user=login(); //进入登录系统
while(true) {
int chioce = user.menu(); //接收选择服务的选项
user.Dooperate(chioce, bookList); //调用 游客/管理员 提供的服务
}
}
}
User类:
package user;
import book.BookList;
import operation.Operate;
public abstract class User {
public String name; //用户名称
public Operate []operate; //创建服务数组,子类通过数组下标调用 各个服务
public User(String name) {
this.name = name; //初始化用户名称
}
public abstract int menu(); //服务菜单
public void Dooperate(int choice,BookList books){
this.operate[choice].work(books); //调用 游客/管理员 所选择的服务
}
}
Administrator类:
package user;
import operation.*;
import java.util.Scanner;
public class Administrator extends User{
public Administrator(String name) {
super(name);//通过父类初始化管理员名称
this.operate=new Operate[]{ //创建 管理员账户提供的服务
new Exitbook(),
new Findbook(),
new Addbook(),
new Deletebook(),
new Showbook()
};
}
@Override
public int menu() {
System.out.println("欢迎 "+this.name+" 管理员来到图书管理系统");
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("<<******************************************>>");
//选择功能
Scanner scanner=new Scanner(System.in);
System.out.println("请选择您需要的服务:-->>");
int choice=scanner.nextInt();
return choice;
}
}
Visitor类:
package user;
import operation.*;
import java.util.Scanner;
public class Visitor extends User{
public Visitor(String name) {
super(name); //通过父类初始化用户名称
this.operate=new Operate[]{ //创建 游客账户提供的服务
new Exitbook(),
new Findbook(),
new Borrowbook(),
new Retuenbook()
};
}
public int menu(){
System.out.println("欢迎 "+this.name+" 读者来到图书管理系统");
System.out.println("<<***************游客读者菜单*************>>");
System.out.println("1. 查找图书 ");
System.out.println("2. 借阅图书 ");
System.out.println("3. 归还图书 ");
System.out.println("0. 退出系统 ");
System.out.println("<<**************************************>>");
Scanner scanner=new Scanner(System.in);
System.out.println("请选择您需要的服务:-->>");
int choice=scanner.nextInt();
return choice;
}
}
Book类:
package book;
public class Book { //书的属性
private String name; //书名
private String author; //作者
private int price; //价格
private String type; //书籍类型
private boolean isborrow; //是否被借出
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 isIsborrow() {
return isborrow;
}
public void setIsborrow(boolean isborrow) {
this.isborrow = isborrow;
}
@Override
public String toString() {
return "Book{" +
"书名='" + name + '\'' +
", 作者='" + author + '\'' +
", 价格=" + price +
", 类型='" + type + '\'' +
(isborrow==true?" ,已经借出":" ,未被借出") +
'}';
}
}
Booklist类:
package book;
public class BookList {
private Book [] books;//表示书架可以存放10本书
private int usedbooks;//表示books数组中存放了几本书
public BookList() {
this.books = new Book [10]; //默认创建存放10本书大小的数组
this.books[0]=new Book("三国演义","罗贯中",20,"四大名著");
this.books[1]=new Book("西游记","吴承恩",22,"四大名著");
this.books[2]=new Book("红楼梦","曹雪芹",24,"四大名著");
this.books[3]=new Book("水浒传","施耐庵",26,"四大名著");
this.usedbooks=4;//初始化有效书本数量为4本
}
public int getUsedbooks() {
return usedbooks;//返回有效书本数量
}
public void setUsedbooks(int usedbooks) {
this.usedbooks = usedbooks;//更改有效书本数量
}
public Book getbook(int pos){
return this.books[pos]; //返回书架中 第pos本书
}
public void setBooks(int pos,Book book){
this.books[pos]=book; //更改书架中的书
}
}
那么operation这个包中各个类的代码都在 实现服务 那里写啦,这里就不在重新上传了~
结语
以上就是利用我们过去的所学知识实现的图书管理系统的基本逻辑构造,在此感谢大家的观看!!!