前言:前面一起和小伙伴们学习了较为完整的Java语法体系,那么本篇将运用这些知识连串在一起实现图书管理系统。
目录
一、总体设计
二、书籍与书架
书籍(Book)
书架(Booklist)
三、对图书的相关操作
IOperations接口
ShowOperation
FindOperation
BorrowOperation
ReturnOperation
AddOperation
DeleteOperation
ExitOperation
三、用户
用户抽象类(User)
NormalUser
AdminUser
Main( 测试 )
注册方法:
main方法:
以面向对象的思想来实现 图书管理系统。
一、总体设计
系统设计框架图:
系统设计思想:
用不同的包来分装不同的类别。共创建book包、user包和operation包。
1、book包
与书相关的有书本与书架,封装共同放入book包,体现了封装的设计思想。
2、user包
user包中用户分为普通用户类与管理员类,共同继承User抽象类,不同的子类有不同的行为现象,这里体现了多态的设计思想。
3、operation包
定义IOperation接口并创建接口数组,再定义不同的图书业务如删除图书类、借阅图书类、归还图书类等等去实现IOperation接口并重写业务方法。并用接口数组间接实例化图书业务对象,通过数组下标来调用不同的图书业务类。
结构图:
二、书籍与书架
书籍(Book)
提供书籍相关信息:
- 书名
- 作者
- 价格
- 类型
- 借出情况
对于成员变量及成员方法,不可盲目地设计其权限性为public,对于这种情况,最好使用private进行封装。
代码如下:(代码中也有适当注释)
package book;
public class Book {
private String name;
private String author;
private int price;
private String type;
private boolean 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==true)? " 已借出":" 未借出")+
// ", isBorrowed=" + isBorrowed +
//注意这里,借出情况信息不应该设置为ture or false
//可以进行如68行修改
'}';
}
}
书架(Booklist)
书架用来存放书籍,书架可以被视为书籍数组,每一个元素都是一本书籍,提供:
- 初始化书籍信息并封装
- 记录存放数量并封装
代码如下:
package book;
public class BookList {
private Book [] books =new Book[10];
private int count;//实际放的书本数
public BookList() {
this.books[0]=new Book("三国演义","罗贯中",20,"小说");
this.books[1]=new Book("西游记","吴承恩",30,"小说");
this.books[2]=new Book("红楼梦","曹雪芹",30,"笑说");
this.count=3;
}
//拿书
public Book getBooks(int pos) {
return books[pos];
}
//设置书的位置
public void setBooks(int pos,Book books) {
this.books[pos] = books;
}
//作用找书
public Book[] getBooks(){
return books;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
三、对图书的相关操作
IOperations接口
ioperation接口的作用:
- 被图书业务操作类实现
- 创建IOperation接口数组,并用接口数组间接实例化图书业务对象,通过数组下标来调用不同的图书业务类。(User类中定义)
提供信息:
- 定义含参 ( 书架 )的work方法
package ioperation;
import book.BookList;
public interface IOperations {
void work(BookList bookList);
}
ShowOperation
ShowOperation内容及作用:
- 重写接口方法
- 打印书籍信息
package ioperation;
import book.Book;
import book.BookList;
public class ShowOperation implements IOperations {
@Override
public void work(BookList bookList) {
//记录书本数量
int count= bookList.getCount();
//遍历数组
for (int i = 0; i < count; i++) {
Book book =bookList.getBooks(i);
// 这里不能直接打印booklist[i],因为 booklist是引用
System.out.println(book);
}
}
}
FindOperation
FindOperation作用:
- 在遍历书籍数组时利用equal方法核对书籍信息
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class FindOperation implements IOperations {
@Override
public void work(BookList bookList) {
System.out.println("查照图书----------");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你要查找的图书书名:");
String name=scanner.nextLine();
int count=bookList.getCount();
for (int i = 0; i < count; i++) {
Book book =bookList.getBooks(i);
if (book.getName().equals(name)){
System.out.println("找到该图书"+book);
return;
}
}
//若找到了图书在22行return返回则运行不到这里
System.out.println("没有找到这本书");
}
}
BorrowOperation
BorrowOperation作用
- 找到需要借阅的书籍更改借阅状态
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class BorrowOperation implements IOperations {
@Override
public void work(BookList bookList) {
System.out.println("借阅图书---------");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要借阅的图书书名--");
String name = scanner.nextLine();
int count = bookList.getCount();
for (int i = 0; i < count; i++) {
Book book = bookList.getBooks(i);
if (book.getName().equals(name)) {
if (book.isBorrowed()) {
System.out.println("这本书已被借出!");
return;
}
//设置借阅情况
book.setBorrowed(true);
System.out.println("借阅成功!");
return;
}
}
System.out.println("没有你要借的这本书");
}
}
ReturnOperation
ReturnOperation内容及作用:
- 找到需要归还的书籍更改借阅状态
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class ReturnOperation implements IOperations {
@Override
public void work(BookList bookList) {
System.out.println("归还图书--------");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你要归还的书:");
String name= scanner.nextLine();
int count= bookList.getCount();
for (int i = 0; i < count; i++) {
Book book = bookList.getBooks(i);
if(book.getName().equals(name)){
//检测前提当前是否被借出
if(book.isBorrowed()){
System.out.println("归还成功!");
//设置为未借出
book.setBorrowed(false);
return;
}
System.out.println("没有你归还的书,归还失败!");
}
}
}
}
AddOperation
AddOperation作用:
- 新增书籍
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class AddOperation implements IOperations {
@Override
public void work(BookList bookList) {
System.out.println("新增图书-------");
//判满
int count=bookList.getCount();
if(count==bookList.getBooks().length){
System.out.println("书架已满!");
}
//输入图书信息
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你要新增的图书书名:");
String name=scanner.nextLine();
System.out.println("请输入作者名称:");
String author =scanner.nextLine();
System.out.println("请输入书本类型:");
String type= scanner.nextLine();
System.out.println("请输入价格:");
int price=scanner.nextInt();
Book newbook=new Book(name,author,price,type);
for (int i = 0; i < count; i++) {
Book book = bookList.getBooks(i);
if (book.getName().equals(name)) {
System.out.println("已存在该图书!");
return;
}
}
//放入新书
bookList.setBooks(count,newbook);
//书本数量加1
bookList.setCount(count+1);
System.out.println("新增图书成功!");
}
}
DeleteOperation
DeleteOperation相对复杂一点
删除步骤:
- 遍历书籍数组记录要删除书本的下标
- 后一个下标的书籍信息依次覆盖当前下标书籍信息,达到删除目的
代码如下:
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class DeleOperation implements IOperations {
@Override
public void work(BookList bookList) {
System.out.println("删除图书------");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你要删除的图书书名:");
String name=scanner.nextLine();
int count=bookList.getCount();
int pos = 0;
int i = 0;
//找到书
for (; i < count; i++) {
Book book = bookList.getBooks(i);
if (book.getName().equals(name)) {
pos = i;
break;
}
}
if(i==count){
System.out.println("没有你要删除的书!");
return;
}
for (int j = pos; j < count-1; j++) {
//拿下标为j+1书
Book book = bookList.getBooks(j+1);
//放入j位置
bookList.setBooks(j,book);
}
//书本数量减1
bookList.setBooks(count-1,null);
bookList.setCount(count-1);
System.out.println("删除成功!");
}
}
ExitOperation
ExitOperation 内容:
- System.exit(0) 退出系统
package ioperation;
import book.BookList;
public class ExitOperation implements IOperations {
@Override
public void work(BookList bookList) {
System.out.println("退出系统--------");
System.exit(0);
}
}
三、用户
用户分为普通用户类与管理员类。
User
创建User抽象类来抽取普通用户类与管理员类的共性,不同的子类有不同的行为现象,这里体现了多态的设计思想。因为User类为抽象类,其访问限定符应设置为protected。
User内容(共性的抽取)
- 定义用户名
- 定义接口数组
- 定义doIoperation方法
doIoperation方法说明:
- 传参数图书业务号码及书架
- 通过对数组下标来访问对应业务
package use;
import book.BookList;
import ioperation.IOperations;
public abstract class User {
protected String name;
//定义接口数组
public IOperations[] ioperations;
public User(String name) {
this.name = name;
}
//抽取共性菜单
protected abstract int menu();
public void doIoperation(int choice, BookList bookList){
ioperations[choice].work(bookList);
}
}
NormalUser
NormalUser继承User类
- 在构造方法中初始化操作数组,并间接实例化操作业务等类的对象
- 打印菜单并返回用户业务数字
package use;
import ioperation.*;
import java.util.Scanner;
public class NormalUser extends User{
public NormalUser(String name) {
super(name);
this.ioperations=new IOperations[]{
new ExitOperation(),
new FindOperation(),
new BorrowOperation(),
new ReturnOperation()
};
}
@Override
protected int menu() {
System.out.println("-----------------------");
System.out.println("1、查找图书");
System.out.println("2、借阅图书");
System.out.println("3、归还图书");
System.out.println("0、退出系统");
System.out.println("-----------------------");
System.out.println("请输入你的选择----------");
Scanner scanner=new Scanner(System.in);
return scanner.nextInt();
}
}
AdminUser
AdminUserr继承User类
- 在构造方法中初始化操作数组,并间接实例化操作业务等类的对象
- 打印菜单并返回用户选择的图书业务数字
package use;
import ioperation.*;
import java.util.Scanner;
public class AdminUser extends User{
public AdminUser(String name) {
super(name);
this.ioperations=new IOperations[]{
new ExitOperation(),
new FindOperation(),
new AddOperation(),
new DeleOperation(),
new ShowOperation()
};
}
@Override
protected 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、退出系统");
System.out.println("-----------------------");
System.out.println("请输入你的选择: ");
Scanner scanner=new Scanner(System.in);
return scanner.nextInt();
}
}
Main( 测试 )
Main为测试类包含
注册方法:
- 根据选择不同实例化不同用户对象并返回(在实例化的同时已经调用了该用户类的构造方法,也就是已经初始化好了用户的图书业务权限)
- 返回类型为User,这里采用了向上转型
main方法:
- 实例化书架
- 调用Login方法获得用户身份(这里转型有疑惑的建议看多态性第五条转型问题)
- 进入循环可以实现一次运行多次选择业务
- 用choice接受用户需要办理的图书业务对应数字
- 调用user的doIoperation方法完成图书操作
package use;
import book.BookList;
import java.util.Scanner;
public class Main {
public static User Login() {
System.out.println("请输入你的名字");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("请输入你的身份: 1、管理员 2、用户");
int choice = scanner.nextInt();
if (choice == 1) {
return new AdminUser(name);
} else if (choice == 2) {
return new NormalUser(name);
}
return null;
}
public static void main(String[] args) {
BookList booklist = new BookList();
User user = Login();
while (true) {
int choice = user.menu();
user.doIoperation(choice, booklist);
}
}
}
写作不易,求路过的朋友们给个三连与关注。有写的不对的地方,欢迎大佬们在评论区指出错误并指导。