本系列可作为JAVA学习系列的笔记,文中提到的一些练习的代码,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。
点赞关注不迷路!您的点赞、关注和收藏是对小编最大的支持和鼓励!
本文篇幅较长,建议先收藏再食用!
系列文章目录
JAVA学习 DAY2 java程序运行、注意事项、转义字符
JAVA学习 DAY5 变量&数据类型 [万字长文!一篇搞定!]
JAVA学习 DAY7 程序逻辑控制【万字长文!一篇搞定!】
JAVA学习 DAY11 类和对象_续1【万字长文!一篇搞定!】
JAVA学习 DAY12 继承和多态【万字长文!一篇搞定!】
JAVA学习 DAY13 抽象类和接口【万字长文!一篇搞定!】
深度剖析 Java 图书管理系统设计与实现:类、接口与对象的实战应用
拓展文章
Java避坑指南:千万别在构造方法中调用重写的方法!(附代码案例+执行流程全解析)
深入剖析 Java 中的深拷贝与浅拷贝:原理、实现与最佳实践
目录
(4)借阅 / 归还操作:BorrowedOperation & ReturnOperation
前言
小编作为新晋码农一枚,会定期整理一些写的比较好的代码,作为自己的学习笔记,会试着做一下批注和补充,如转载或者参考他人文献会标明出处,非商用,如有侵权会删改!欢迎大家斧正和讨论!
在面向对象编程(OOP)的学习过程中,图书管理系统是经典的实战案例,它能完整覆盖类、接口、继承、多态、封装 等核心知识点。本文将基于一份完整的图书管理系统代码,从需求设计、类结构、接口设计、对象交互等维度,详细拆解系统的设计思路与实现细节,帮助读者理解 OOP 思想在实际项目中的落地方式。
一、系统整体设计思路
该图书管理系统核心目标是实现管理员和普通用户两类角色的图书管理操作,核心功能包括:
- 管理员:查找、新增、删除、显示图书、退出系统
- 普通用户:查找、借阅、归还图书、退出系统
系统采用面向接口编程 + 多态 的设计模式,将 “操作” 抽象为接口,不同操作实现接口方法;通过用户类的继承体系区分角色权限,最终通过对象交互完成业务逻辑闭环。
系统核心架构分层
| 层级 | 对应类 / 接口 | 职责说明 |
|---|---|---|
| 数据层 | Book、BookList | 封装图书数据、管理图书集合 |
| 操作层 | IOperation 及实现类 | 定义并实现图书的具体操作 |
| 用户层 | User、AdminUser、NormalUser | 封装用户信息、提供操作入口 |
| 入口层 | Main | 系统启动、用户登录、流程控制 |
二、数据层设计:封装图书与图书集合
数据层是系统的基础,负责存储和管理核心数据,核心类为Book(图书)和BookList(图书列表),体现了 OOP 的封装特性。
1. Book 类:封装图书属性与行为
Book类是典型的 “实体类”,封装了图书的所有属性,并提供访问器(getter)和修改器(setter)方法,同时重写toString方法方便打印图书信息。
核心代码与分析
package book;
public class Book {
// 私有属性:封装性体现,外部无法直接访问
private String name; // 书名
private String author; // 作者
private int price; // 价格
private String type; // 类型
private boolean isBorrowed;// 借阅状态
// 构造方法:初始化图书属性(未借出状态默认false)
public Book(String name, String author, int price, String type) {
this.name = name;
this.author = author;
this.price = price;
this.type = type;
}
// 重写toString:自定义图书信息打印格式,包含借阅状态
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", type='" + type + '\'' +
((isBorrowed==true)?"已借出":"未借出")+
'}';
}
// Getter/Setter:控制属性的访问与修改,符合封装原则
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public boolean isBorrowed() { return isBorrowed; }
public void setBorrowed(boolean borrowed) { isBorrowed = borrowed; }
// 其他属性的getter/setter省略...
}
设计亮点
- 封装性:所有属性私有化,仅通过方法暴露必要的访问入口,避免属性被随意修改(例如借阅状态
isBorrowed只能通过setBorrowed修改); - 行为内聚:将图书的 “属性” 和 “展示方法(toString)” 封装在一个类中,符合 “单一职责原则”;
- 状态管理:通过
isBorrowed布尔值管理借阅状态,为后续借阅 / 归还操作提供数据支撑。
2. BookList 类:管理图书集合
BookList类是图书的 “容器类”,内部维护一个Book类型的数组,同时管理数组的 “有效元素数量(usedSize)”,提供图书的增、删、查、改方法,是系统的 “图书仓库”。
核心代码与分析
package book;
public class BookList {
// 图书数组:容量固定为10(可扩展为动态数组)
private Book[] books=new Book[10];
// 有效图书数量:标记数组中已存放的图书个数
private int usedSize;
// 构造方法:初始化默认图书(系统启动时自带3本图书)
public BookList() {
this.books[0]=new Book("三国演义","罗贯中",21,"小说");
this.books[1]=new Book("水浒传","施耐庵",23,"小说");
this.books[2]=new Book("红楼梦","曹雪芹",33,"小说");
this.usedSize = 3;
}
// 获取/设置有效数量:控制数组的实际使用范围
public int getUsedSize() { return usedSize; }
public void setUsedSize(int usedSize) { this.usedSize = usedSize; }
// 获取指定位置的图书:用于遍历/查找图书
public Book getBooks(int pos) { return books[pos]; }
// 设置指定位置的图书:用于新增/删除图书
public void setBooks(int pos, Book book) { this.books[pos] = book; }
}
设计亮点
- 数据隔离:将图书数组私有化,外部只能通过
getBooks/setBooks操作指定位置的图书,避免数组越界或非法修改; - 容量控制:通过
usedSize管理有效图书数量,遍历 / 操作图书时只需处理0~usedSize-1范围,提升效率; - 初始化数据:构造方法中预设 3 本图书,避免系统启动时无数据,提升测试体验。
三、操作层设计:接口化设计实现行为抽象
操作层是系统的核心业务层,通过IOperation接口定义所有图书操作的规范,不同操作(查找、新增、删除等)实现该接口,体现接口的抽象性和多态性。
1. IOperation 接口:定义操作规范
接口是 “行为契约”,IOperation仅定义一个work方法,规定所有图书操作必须接收BookList参数(操作的目标图书集合),无返回值。
核心代码与分析
package ioperation;
import book.BookList;
// 所有图书操作的统一接口:面向接口编程的核心
public interface IOperation {
// 操作的核心方法:接收BookList,对图书集合进行操作
void work(BookList bookList);
}
设计意义
- 规范统一:所有操作类必须实现
work方法,保证操作的入口统一,便于用户层调用; - 解耦设计:用户层只需依赖
IOperation接口,无需关注具体操作的实现细节,符合 “依赖倒置原则”; - 扩展灵活:新增操作时只需实现
IOperation接口,无需修改现有代码,符合 “开闭原则”。
2. 操作类实现:多态的具体体现
所有操作类(如FindOperation、AddOperation、BorrowedOperation等)都实现IOperation接口,并重写work方法,完成具体业务逻辑。以下选取核心操作类分析:
(1)查找操作:FindOperation
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class FindOperation implements IOperation{
@Override
public void work(BookList bookList){
System.out.println("正在查找图书...");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你的书名:");
String name=scanner.nextLine();
// 遍历有效图书,匹配书名
int currentSize=bookList.getUsedSize();
for(int i=0;i<currentSize;i++){
Book book=bookList.getBooks(i);
if(book.getName().equals(name)){
System.out.println("找到了这本书");
System.out.println(book);
return; // 找到后直接返回,避免无效遍历
}
}
System.out.println("没有你要找到这本书...");
}
}
设计分析:
- 依赖
BookList获取图书集合,通过getUsedSize限定遍历范围; - 核心逻辑是 “书名匹配”,找到后打印图书信息(复用
Book的toString方法); - 交互友好:通过
Scanner接收用户输入,操作结果明确反馈。
(2)新增操作:AddOperation
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class AddOperation implements IOperation{
@Override
public void work(BookList bookList){
System.out.println("增加图书...");
// 1. 判断书架是否已满
int currentSize=bookList.getUsedSize();
if(currentSize==bookList.getBooks().length){
System.out.println("书架满了,不能放了");
return;
}
// 2. 接收用户输入,构建新图书对象
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);
// 3. 判断图书是否已存在
for(int i=0;i<currentSize;i++){
Book book=bookList.getBooks(i);
if(book.getName().equals(name)){
System.out.println("这本书已经有了,不能添加");
return;
}
}
// 4. 新增图书到数组末尾,更新有效数量
bookList.setBooks(currentSize, newBook);
bookList.setUsedSize(currentSize+1);
System.out.println("新增成功");
}
}
设计分析:
- 边界校验:先判断书架容量,避免数组越界;
- 重复校验:新增前检查图书是否已存在,保证数据唯一性;
- 数据更新:新增后更新
usedSize,保证后续操作的有效性。
(3)删除操作:DelOperation
package ioperation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class DelOperation implements IOperation{
@Override
public void work(BookList bookList){
System.out.println("删除图书...");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你要删除的书名:");
String name=scanner.nextLine();
int currentSize=bookList.getUsedSize();
int pos=-1; // 标记要删除的图书位置
// 1. 查找图书位置
int i=0;
for(;i<currentSize;i++){
Book book=bookList.getBooks(i);
if(book.getName().equals(name)){
pos=i;
break;
}
}
if (i==currentSize){ // 未找到图书
System.out.println("没有你要删的书......");
return;
}
// 2. 数组前移:覆盖要删除的位置
for (int j = pos; j < currentSize-1; j++) {
Book book=bookList.getBooks(j+1);
bookList.setBooks(j,book);
}
// 3. 清空最后一个位置,更新有效数量
bookList.setBooks(currentSize-1,null);
bookList.setUsedSize(currentSize-1);
System.out.println("删除成功!!!");
}
}
设计分析:
- 位置标记:通过
pos记录删除位置,避免遍历过程中直接修改数组; - 数组前移:删除逻辑采用 “覆盖法”,将后续元素前移,符合数组删除的常规实现;
- 资源释放:将最后一个有效位置设为
null,帮助 GC 回收内存。
(4)借阅 / 归还操作:BorrowedOperation & ReturnOperation
- 借阅操作:核心是修改图书的
isBorrowed为true,并校验是否已借出; - 归还操作:核心是修改图书的
isBorrowed为false,校验图书是否存在。
// 借阅操作核心逻辑
if(book.getName().equals(name)){
if (book.isBorrowed()){
System.out.println("这本书已经被借出");
return;
}
book.setBorrowed(true);
System.out.println("借阅成功!");
return;
}
// 归还操作核心逻辑
if (book.getName().equals(name)){
book.setBorrowed(false);
System.out.println("归还成功");
return;
}
设计分析:
- 状态校验:借阅前检查是否已借出,避免重复借阅;
- 状态修改:通过
setBorrowed修改借阅状态,符合Book类的封装设计; - 快速返回:找到目标图书后立即返回,提升执行效率。
3. 退出操作:ExitOperation
package ioperation;
import book.BookList;
public class ExitOperation implements IOperation{
@Override
public void work(BookList bookList){
System.out.println("退出系统...");
System.exit(0); // 终止JVM,退出程序
}
}
设计分析:最简单的操作类,通过System.exit(0)终止程序,是系统的 “退出开关”。
四、用户层设计:继承与多态实现角色区分
用户层是系统的 “入口层”,通过User抽象类定义用户的通用行为,AdminUser(管理员)和NormalUser(普通用户)继承该类,重写menu方法实现不同的菜单展示,并通过IOperation数组绑定不同的操作权限,体现继承和多态的核心思想。
1. User 抽象类:定义用户通用规范
User是抽象类,包含用户的通用属性(姓名)和行为(菜单展示、执行操作),其中menu方法为抽象方法,强制子类实现(不同角色菜单不同)。
核心代码与分析
package user;
import book.BookList;
import ioperation.IOperation;
// 抽象类:不能实例化,仅作为父类提供通用行为
public abstract class User{
// 受保护属性:子类可直接访问,外部不可见
protected String name;
// 操作数组:存储该用户可执行的操作(多态的核心载体)
IOperation[] ioprations;
// 构造方法:初始化用户名
public User(String name) {
this.name = name;
}
// 抽象方法:子类必须实现,返回用户选择的操作编号
public abstract int menu();
// 执行操作:根据选择的编号,调用对应操作的work方法
public void doIoperation(int choice, BookList bookList){
ioprations[choice].work(bookList);
}
}
设计亮点
- 抽象性:
menu方法抽象化,保证不同角色(管理员 / 普通用户)必须实现自己的菜单; - 多态载体:
IOperation[]数组存储不同操作对象,调用时无需区分具体操作类型,直接通过choice索引调用work方法; - 职责分离:
User类只负责 “接收用户选择” 和 “执行操作”,具体操作逻辑由IOperation实现类完成,符合 “单一职责原则”。
2. 管理员用户:AdminUser
AdminUser继承User,重写menu方法展示管理员菜单,并初始化IOperation[]数组绑定管理员可执行的操作(查找、新增、删除、显示、退出)。
核心代码与分析
package user;
import ioperation.*;
import java.util.Scanner;
public class AdminUser extends User{
// 构造方法:初始化管理员的操作数组
public AdminUser(String name) {
super(name);
this.ioprations=new IOperation[]{
new ExitOperation(), // 0. 退出
new FindOperation(), // 1. 查找
new AddOperation(), // 2. 新增
new DelOperation(), // 3. 删除
new ShowOperation() // 4. 显示
};
}
// 重写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;
}
}
设计分析
- 操作绑定:
ioprations数组的索引与菜单编号一一对应(如choice=1对应FindOperation),用户选择编号后可直接调用对应操作; - 权限控制:管理员的操作数组包含新增、删除、显示等权限,普通用户无这些操作,实现角色权限隔离;
- 继承复用:通过
super(name)调用父类构造方法,复用用户名初始化逻辑。
3. 普通用户:NormalUser
NormalUser继承User,重写menu方法展示普通用户菜单,绑定的操作仅包含查找、借阅、归还、退出,符合普通用户的权限范围。
核心代码与分析
package user;
import ioperation.*;
import java.util.Scanner;
public class NormalUser extends User{
public NormalUser(String name) {
super(name);
this.ioprations=new IOperation[]{
new ExitOperation(), // 0. 退出
new FindOperation(), // 1. 查找
new BorrowedOperation(),// 2. 借阅
new ReturnOperation() // 3. 归还
};
}
@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("*****0.退出系统*****");
System.out.println("*******************");
Scanner scanner=new Scanner(System.in);
System.out.println("请输入你的操作:");
int choice=scanner.nextInt();
return choice;
}
}
设计分析
- 权限隔离:普通用户无新增、删除、显示图书的权限,操作数组仅包含核心的借阅 / 归还操作;
- 菜单匹配:菜单编号与操作数组索引严格对应,保证用户选择的操作能被正确执行。
五、入口层设计:Main 类实现系统流程控制
Main类是系统的入口,负责用户登录、创建图书集合、循环展示菜单并执行操作,是整个系统的 “总指挥”。
核心代码与分析
import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
public class Main {
// 登录方法:根据用户输入的身份,返回对应的User子类对象(多态)
public static User login(){
Scanner scanner=new Scanner(System.in);
System.out.println("请输入姓名:");
String name=scanner.nextLine();
System.out.println("请输入身份:1.管理员 2.普通用户");
int type=scanner.nextInt();
if (type==1){
return new AdminUser(name); // 向上转型为User
}else{
return new NormalUser(name); // 向上转型为User
}
}
public static void main(String[] args) {
// 1. 创建图书集合(初始化默认3本图书)
BookList bookList=new BookList();
// 2. 用户登录,返回User对象(多态:实际为AdminUser/NormalUser)
User user= login();
// 3. 循环执行:展示菜单 -> 执行操作
while(true){
int choice=user.menu(); // 调用子类的menu方法(多态)
user.doIoperation(choice, bookList); // 执行对应操作
}
}
}
设计亮点
- 多态核心:
login方法返回User类型,但实际返回的是AdminUser或NormalUser对象,调用menu和doIoperation方法时,会自动执行子类的实现,体现 “编译时类型与运行时类型分离” 的多态特性; - 循环流程:
while(true)循环保证系统持续运行,直到用户选择退出(ExitOperation执行System.exit(0)); - 对象创建:
BookList对象在main方法中创建,作为参数传递给所有操作类,保证所有操作共享同一个图书集合。
六、系统设计的核心知识点总结
1. 类与对象
- 类:
Book、BookList、User等都是类,是对 “图书”“用户” 等实体的抽象描述; - 对象:
new BookList()、new AdminUser(name)等创建对象,是类的具体实例,承载实际的数据和行为; - 封装:
Book类的私有属性 + getter/setter,BookList的数组私有化,都体现封装的核心思想 —— 隐藏内部细节,暴露必要接口。
2. 接口
- 接口的抽象性:
IOperation接口仅定义work方法,不关注具体实现,是所有操作类的 “行为契约”; - 接口的多态性:
IOperation[]数组可以存储任意实现类的对象,调用work方法时自动执行对应实现,无需区分具体操作类型; - 面向接口编程:用户层仅依赖
IOperation接口,新增操作时只需实现接口,无需修改现有代码,提升系统扩展性。
3. 继承与多态
- 继承:
AdminUser和NormalUser继承User类,复用用户名属性和doIoperation方法,仅需重写menu方法; - 多态:
- 向上转型:
User user = new AdminUser(name); - 方法重写:子类重写
menu方法; - 动态绑定:运行时根据
user的实际类型,调用对应的menu方法。
- 向上转型:
4. 设计原则
- 单一职责原则:每个类只负责一个核心功能(
Book管图书数据,FindOperation管查找逻辑); - 开闭原则:新增操作时只需实现
IOperation接口,无需修改现有代码; - 依赖倒置原则:用户层依赖
IOperation接口,而非具体操作类,降低耦合。
七、系统扩展与优化建议
- 动态数组优化:
BookList中的图书数组容量固定为 10,可改为ArrayList<Book>实现动态扩容; - 异常处理:当前代码未处理用户输入非法字符(如输入非数字的操作编号),可添加
try-catch捕获异常; - 持久化存储:当前数据仅存在于内存中,程序退出后丢失,可结合 IO 流将图书数据保存到文件;
- 权限细化:可新增用户注册、密码验证功能,提升系统安全性;
- 批量操作:新增批量删除、批量借阅等功能,提升操作效率。
八、总结
该图书管理系统是面向对象编程的经典实践,完整覆盖了类、对象、接口、继承、多态、封装 等核心知识点。通过 “数据层 - 操作层 - 用户层 - 入口层” 的分层设计,实现了业务逻辑的解耦;通过接口化设计和多态特性,提升了系统的扩展性和维护性。
从代码中可以清晰看到:类是对象的模板,接口是行为的契约,继承是复用的手段,多态是灵活的核心。理解这些知识点的落地方式,不仅能掌握 Java OOP 的核心思想,也能为后续学习设计模式、大型项目开发奠定基础。

总结
以上就是今天要讲的内容,本文简单记录了JAVA学习笔记,大家根据注释理解,您的点赞关注收藏就是对小编最大的鼓励!

1769

被折叠的 条评论
为什么被折叠?



