面向对象是Java中最重要的思想,本图书管理系统就是以面向对象为中心,逐层拆解业务。
首先抽象出对象,一想到图书管理系统,我们就会想到 书和 能操作书的人 。
但只有书还不够 还需要 一个书架 来进行管理
那么 总结 下来
我们需要创建 书类(Book) 、管理书的书架类(BookList)、用户类(User)
每个事物都有自己的属性,那么我们就需要考虑 这三个类 都有什么成员属性和成员方法
自定义类
- Book类
成员属性:书名(name),作者名(author),价格(price),类型(type),是否被借出的状态(state)
构造方法:初始化Book
成员方法:因为我们不希望外界干扰这些关键信息,因此都需要用 private 修饰。因此每个成员属性都要有 get 和 set 方法
- BookList类
书架上需要放很多的书,那么书籍的底层数据结构用数组最合适不过了
成员属性:书架(Book[] books),书架的长度(usedSize)
构造方法:初始化Books (默认有三本书)
成员方法:因为我们不希望外界干扰这些关键信息,因此都需要用 private 修饰。因此每个成员属性都要有 get 和 set 方法
- User类
对于用户来说 要 分为 管理权限高的 管理员和 权限比较低的 普通用户。
管理员的权限功能: 显示图书、增加图书、删除图书、查询图书、退出系统
普通用户的权限功能:查询图书、借阅图书、归还图书、退出系统
那么我们要根据用户的不同来分别呈现对应的菜单功能,因此我们需要借助多态的思想。
但实现多态的前提,需要继承,因此我们需要有User这个大类,并让普通用户(NomralUser)和 管理员(AdminUser) 继承User。
成员属性:姓名(name)
构造方法:初始化name
成员方法:菜单选项(menu)
因为用户不同,所以对应的菜单打印也不同,因此 NomralUser 和 AdminUser类 也都需要重写父类的 menu方法。那么 menu 方法 应该由 abstract 修饰 并且 User类也不能用来具体表示某个对象只是泛称因此也要用 abstract 修饰。
自定义接口
因为 NomralUser 和 AdminUser 对于的菜单操作方法不同,我们可以创建接口数组,利用接口数组组织这些操作,需要用到哪个直接按照用户输入的数字,调用出对应数组下标的操作方法。
但接口并不能直接创建和实现, 因此 我们需要对每个操作都创建对应的类 然后 将这些类实现接口。
"管理员" 需要的操作:显示图书信息、增加图书信息、删除图书信息、查询图书信息、退出系统
"用户" 需要的操作:查询图书信息、借阅图书、归还图书、退出系统
这些操作,分别定义成 类 :
"Add" 增加
"Delete" 删除
"Show" 显示
"Find" 查找
"Borrow" 借阅
"Return" 归还
"Exit" 退出
让这些 类 都 实现Operation 这个接口,在 Operation 接口中 定义一个抽象方法: work() ,这样就只需要在这些 类 中重写 **work()**方法即可
代码书写
我们根据上面的这些 分析,进行编写代码
book 包
创建一个 book包 里面有 Book类 和 BookList类
Book类
java
package book;
public class Book {
private String name;
private String author;
private int price;
private String type;
private boolean 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 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 isState() {
return state;
}
public void setState(boolean state) {
this.state = state;
}
public Book(String name, String author, int price, String type) {
this.name = name;
this.author = author;
this.price = price;
this.type = type;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", type='" + type + '\'' +
(state == true ? "已借出": "未借出") +
// ", state=" + state +
'}';
}
}
可以看到构方法中没有 state 这个参数,是因为 boolean 类型的变量即使不初始化,系统也会赋给一个默认值,默认为 "false"
BookList类
java
package book;
public class BookList {
private Book[] books = new Book[10];
private int usedSize;
public BookList(Book[] books, int usedSize) {
books[0] = new Book("铁道概论","张三",10,"教科书");
books[1] = new Book("电路分析基础","李四",15,"教科书");
books[0] = new Book("区间闭塞设备维修","王五",20,"教科书");
this.usedSize = 3;
}
public int getUsedSize() {
return usedSize;
}
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
}
}
创建书架时,默认书架上有三本书
user包
创建一个user包,里面分别有 User 父类,继承User的子类 NomralUser 和 AdminUser类
User类
java
package user;
//因为User不能表达某个具体的对象
//并且有抽象方法,因此为抽象类
import book.BookList;
public abstract class User {
protected String name;
protected IOPeration[] ioPerations;//接口数组 分别放置不同的操作
public User(String name) {
this.name = name;
}
//抽象方法的原因,根据子类各自的情况,呈现不同的菜单详情,因此父类 menu 方法 不用有具体实现
public abstract int menu();
}
AdminUser 子类
java
package user;
public class AdminUser extends User{
public AdminUser(String name) {
super(name);
}
@Override
public void 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("------------------------------------------------");
}
}
NomralUser 子类
java
public class NomralUser extends User{
public NomralUser(String name) {
super(name);
}
@Override
public void menu() {
System.out.println("------------普通用户菜单------------");
System.out.println("1.查找图书");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("0.退出系统");
System.out.println("------------------------------------------------");
}
}
operation包
存放接口 IOPeration,和其他操作类
添加图书:AddOperation
借阅图书:BorrowedOpreation
删除图书:DelOperation
退出系统:ExitOpreation
寻找图书:FindOperation
归还图书:ReturnOpreation
显示图书:ShowOperation
接口 IOPeration
java
package operation;
import book.BookList;
public interface IOPeration {
void work(BookList booklist);
}
AddOperation类
java
public class AddOperation implements IOperation{
@Override
public void work() {
}
}
BorrowedOpreation类
java
public class BorrowedOpreation implements IOperation{
@Override
public void work() {
}
}
DelOperation类
java
public class DelOperation implements IOperation{
@Override
public void work() {
}
}
ExitOpreation类
java
public class ExitOpreation implements IOperation{
@Override
public void work() {
}
}
FindOperation类
java
public class FindOperation implements IOperation{
@Override
public void work() {
}
}
ReturnOpreation类
java
public class ReturnOpreation implements IOperation {
@Override
public void work() {
}
}
ShowOperation类
java
public class ShowOperation implements IOperation{
@Override
public void work() {
}
}
基本准备工作准备好了之后,我们就要代入操作者的视角,进行操作内容的搭建
-
登录系统
-
选择身份
-
选择想要进行的操作
程序入口
我们可以在src包下创建一个Main类,作为程序的入口
Main类
java
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){
AdminUser adminUser = new AdminUser(name);
return adminUser;
} else{
NomralUser nomralUser = new NomralUser(name);
return nomralUser;
}
}
public static void main(String[] args) {
//第一步 创建书架
BookList bookList = new BookList();
//第二步 根据输入,获取用户权限信息
//向上转型
User user = login();
我们根据输入的数字进入new对应身份的对象,然后用 User父类引用对象 接收,这里就是向上转型,并为下面根据 不同的身份打印不同的菜单(多态)提供了前提条件

java
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){
AdminUser adminUser = new AdminUser(name);
return adminUser;
} else{
NomralUser nomralUser = new NomralUser(name);
return nomralUser;
}
}
public static void main(String[] args) {
//第一步 创建书架
BookList bookList = new BookList();
//第二步 根据输入,获取用户权限信息
//向上转型
User user = login();
//第三步 利用多态思想 打印对应菜单 并获取 选项
int choice = user.menu();
}

接下来我们只剩下对 操作的处理
因为 管理员 和 普通用户 既有相同操作又有不同的操作,那么我们就需要用接口数组。在数组中存放相应的操作,当用户输入操作数字,我们只需根据输入 将数组对应下标的方法调用即可。
所以我们在 User 父类中:
补充一个成员属性:IOperations 数组,只声明即可,在子类中利用构造方法帮助父类进行初始化这个数组
补充一个成员方法: doIoperation(),利用下标访问对应的类中的 work 方法
补充 User 父类
java
public abstract class User {
protected String name;
//新增
protected IOperation[] ioPerations;
public User(String name) {
this.name = name;
}
public abstract int menu();
//新增
public void doIoperation(int choice, BookList booklist) {
this.ioPerations[choice].work(booklist);
}
}
补充子类的构造方法
java
public AdminUser(String name) {
super(name);
this.ioPerations = new IOPeration[]{
new ExitOperation(),
new FindOperation(),
new AddOperation(),
new DelOperation(),
new ShowOpreation()
};
}
java
public NormalUser(String name) {
super(name);
this.ioPerations = new IOPeration[]{
new ExitOperation(),
new FindOperation(),
new BorrowedOperation(),
new ReturnOperation()
};
}
根据构造方法,就可以初始化数组了
最后补全方法调用语句 user.doIoperation();
java
public static void main(String[] args) {
//第一步 创建书架
BookList bookList = new BookList();
//第二步 根据输入,获取用户权限信息
//向上转型
User user = login();
//第三步 利用多态思想 打印对应菜单 并获取 选项
int choice = user.menu();
//调用方法 体现了动态绑定
user.doIoperation(choice,bookList);
}
最后我们只剩具体操作的核心逻辑了
补全操作
AddOperation类
java
public class AddOperation implements IOPeration{
public void work(BookList bookList){
System.out.println("新增图书");
if(bookList.isFull()){
System.out.println("书架满了 不能新增了");
return;
}
System.out.println("请输入你要新增的图书的书名");
Scanner scanner = new Scanner(System.in);
String bookName = scanner.nextLine();
System.out.println("请输入你要新增的图书的作者");
String author = scanner.nextLine();
System.out.println("请输入你要新增的图书的类型");
String type = scanner.nextLine();
System.out.println("请输入你要新增的图书的价格");
int price = scanner.nextInt();
Book book = new Book(bookName,author,price,type);
//在数组的末尾加入数据
int currentSize = bookList.getUsedSize();
bookList.setBook(currentSize,book);
bookList.setUsedSize(currentSize+1);
System.out.println("新增图书成功!");
}
}
BorrowedOperation类
java
public class BorrowedOperation implements IOPeration{
public void work(BookList bookList){
System.out.println("借阅图书");
System.out.println("请输入你想要借阅的图书");
Scanner scanner = new Scanner(System.in);
String bookName = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
Book book = bookList.getBook(i);
if(book.getName().equals(bookName)){
book.setState(true);
System.out.println("借阅成功");
return;
}
}
System.out.println("借阅失败");
}
}
DelOperation类
java
public class DelOperation implements IOPeration{
public void work(BookList bookList){
System.out.println("删除图书");
System.out.println("请输入你要删除的图书的书名: ");
Scanner scanner = new Scanner(System.in);
String bookName = scanner.nextLine();
int currentSize = bookList.getUsedSize();
//初始化下标
int pos = -1;
int i = 0;
for (; i < currentSize; i++) {
Book book = bookList.getBook(i);
if (book.getName().equals(bookName)){
//代码执行到这里时,已经说明 找到了这本书
//记录下标
pos = i;
break;
}
}
if (i >= currentSize){
System.out.println("没有你要删除的图书");
return;
}
//开始删除
for(int j = pos; j < currentSize - 1;j++){
bookList.setBook(j,bookList.getBook(j+1));
// Book book = bookList.getBook(j+1);
// bookList.setBook(j,book);
}
//删除之后,修改usedSize
bookList.setUsedSize(currentSize-1);
bookList.setBook(currentSize-1 ,null);
}
}
ExitOperation类
java
public class ExitOperation implements IOPeration{
public void work(BookList bookList){
System.out.println("退出系统");
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
bookList.setBook(i,null);
}
// 0 代表正常退出
System.exit(0);
}
}
FindOperation类
java
public class FindOperation implements IOPeration{
public void work(BookList bookList){
System.out.println("寻找图书");
System.out.println("请输入你要查找的图书名:");
Scanner scanner = new Scanner(System.in);
String bookName = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for(int i = 0; i < currentSize; i++){
Book book = bookList.getBook(i);
if(book.getName().equals(bookName)){
System.out.println("找到了这本书:");
System.out.println(book);
//因为重写了Book 的 toString 方法
return;
}
}
System.out.println("没有你要找的书");
}
}
ReturnOperation类
java
public class ReturnOperation implements IOPeration{
public void work(BookList bookList){
System.out.println("归还图书");
System.out.println("请输入你想要归还的图书");
Scanner scanner = new Scanner(System.in);
String bookName = scanner.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
Book book = bookList.getBook(i);
if(book.getName().equals(bookName)){
book.setState(false);
System.out.println("归还成功");
return;
}
}
System.out.println("归还失败");
}
}
ShowOpreation类
java
public class ShowOpreation implements IOPeration{
public void work(BookList bookList){
System.out.println("显示图书");
int currentSize = bookList.getUsedSize();
for(int i = 0;i < currentSize; i++){
Book book = bookList.getBook(i);
System.out.println(book);
}
}
}