图片出处:The world's biggest drone photo and video sharing platform | SkyPixel.com
导言
在学完JavaSE语法后,我们就可以去尝试写一个简单的图书管理系统来进一步提升我们面对对象编程的思想。在该系统中会涉及到数组,接口,封装,继承,多态等等语法知识,希望能够帮助到大家!
1,需求分析
(1)找对象
在开始编写代码之前,我们需要先找到该系统可能涉及的对象,如下:
书
书架
管理员
普通用户
(2)功能设计
我将根据使用者访问权限的不同,计划分为两个使用者类,如下:
管理员:
- 上架图书
- 下架图书
- 查找图书
- 显示所有图书
- 修改图书状态
- 退出系统
普通用户:
- 借阅图书
- 归还图书
- 查找图书
- 图书借阅排行榜
- 退出系统
可以看出,上述所有功能都是依赖于书架进行操作的,但是由于需要区分使用权限,故将所有功能统一放在一个包中,再在用户类中以转移表的方式进行调用,此操作在后续会进行详细讲解。
2,创建对象
当找到对象后,就可以开始创建对象,我们可以先将所想到的属性详尽地描述,后续再查漏补缺。同时,在创建对象时需要注意类的封装性。
(1)使用包对类进行管理
在创建对象之前,先按照对象的类型创建三个包:
aboutTheBook --关于书的包,存放书架,书等类
aboutUsers --关于用户的包,存放管理员,普通用户等类
operations --关于操作方法的包
(2)对象的创建
(1)aboutTheBook包
<1>Book类
对于Book类而言,可根据具体需求对其添加属性,并且由于它是本系统中最基础的操作单位,故要对其进行封装。
<2>BookShelf
BookShelf类主要用来存放书,并对书进行管理。此处我使用的是数组结构,如下:![](https://img-blog.csdnimg.cn/direct/14294e86ea124e3da3b0a49b71db55ff.png)
(2)operations包
<1>IOperation类
在operation包中存放的是所有和图书管理有关的操作方法类,故我创建了接口IOperation,并让每个类都实现该接口。由此便可使用 IOperation类型数组对所有的方法进行组织。
目前IOPeration接口代码如下:
(因为所有的操作都是围绕书架进行的,故work的参数列表中应当传递BookShelf)![](https://img-blog.csdnimg.cn/direct/04b6495df2f34c5292c2a4bf969923fd.png)
<2>操作方法类
操作方法在后文中会详细地讲到,目前只是代码框架的搭建,以Add类为例,目前每个类的实现如下:
(3)aboutUsers包** **
<1>User类
在aboutTheBook包中,我定义了三个类,分别是抽象类User,普通类AdminUser,普通类NormalUser,其中AdminUser类和NormalUser类均继承于User类。
那么为什么需要定义一个抽象类呢?如下:
上图是目前User类的全部代码,可以看到在该类中声明了两个抽象方法,分别是:
public abstract int menu(); -->打印菜单,并且返回所输入的值
public abstract void doOperation(int choose, BookShelf bookShelf); -->转移表操作
AdminUser类 和 NormalUser类 继承 User类,并且重写 User类 的抽象方法,那后续就可以直接使用父类类型去实例化子类对象,再调用重写方法,此时就会发生动态绑定,直接调用所引用的子类的重写方法,从而实现多态性。
届时,我们只需要根据用户选择的登录方法返回相应的实例化对象交给User类型接收,直接使用User类型变量去调用方法即可。
<2>AdminUser类 与 NormalUser类
AdminUser类:
NormalUser类:
通过上述代码可以看到,AdminUser类与NormalUser类只需对父类中的抽象方法进行实现即可,并无其它自有的属性。唯一的区别在于:由于操作权限的不同,导致菜单与转移表的内容不同。
menu方法逻辑注解:
(以NormalUser为例)![](https://img-blog.csdnimg.cn/direct/c9c85e8025c347ff8e8dfc581d9e224a.png)
doOperation方法逻辑注解:
(以NormalUser为例)![](https://img-blog.csdnimg.cn/direct/3d42b41b627544219df5aa0f9e2cdd19.png)
3,代码框架搭建
在前文中,我们已经完成找对象与使用对象这两个步骤,接下来我们利用对象之间的交互来实现代码框架的代码,通过Main类中的main函数将所有类、方法、接口串联起来。
(1)login方法
在运行程序之初,我们需要完成用户登录这一操作,故封装login方法,代码如下:![](https://img-blog.csdnimg.cn/direct/16d5b563dcca4e5fb4e26728b5d1caf0.png)
(2)main方法 ==> 代码总逻辑
main方法代码如下:
代码逻辑如下(假设login返回的是NormalUser的实例对象):
(每个函数具体的实现逻辑在上文均有详细讲解,图中黄线为主逻辑,红线为所调用的代码)
(3)框架测试
(实际测试了很多情况,上图为最基本的使用场景)
至此,代码框架均已搭建完毕,而操作方法的具体实现会在下文中进行详细讲解。
4,具体功能实现
对于一些接口的方法会在下面类中重复使用到,我仅对其第一次出现时进行解答,后续再出现将不再赘述
(1)Show类
为了能够更好地展示后续对图书的上架,下架等操作,故先实现Show类。
Show的功能设定为展示所有图书,顾名思义就是将打印顺序表中的所有有效元素。分两个步骤:判空和打印。考虑到后续其它类的实现也会使用到判空,故我创建了ICheckIsEmpty接口用于判空。
不过直接使用 System.out.println 打印对象其真实打印的是对象的地址,故我们还需要先在Book类中重写 toString 方法,如下:
代码实现如下:![](https://img-blog.csdnimg.cn/direct/b8c28ed70a9a438aafa9a7dd57ef9b29.png)
控制台示例输出如下:
(2)Add类
Add的功能设定为上架图书,即是增加元素。既然是增加元素,那么就需要考虑空间是否已经满了,若是满了则需要扩容后再添加元素。为此,我创建了ICheckCapacity接口用于检查内存。
由于其需要在书架中添加书,所以需要先在BookShelf类中新增一个 **设置pos位置数据** 的对外方法,如下:
Add类代码如下:![](https://img-blog.csdnimg.cn/direct/1bfea8876a724d1db2d9bd7774daa936.png)
控制台示例输出如下:
(3)Delete类
Delete类的功能设定为下架图书,实际就是在书架中删除该图书。在删除之前需要判断两个前置条件:
1:书架不能为空
2:待删除的书不能不存在
故我们除去判空接口之外,还需要创建一个查找接口,用于查找特定的元素,并返回其下标,具体实现如下:![](https://img-blog.csdnimg.cn/direct/82ba7cd180f2434d921480554907361d.png)
控制台示例输出如下:
(4)Borrow类 和 Return类
Borrow类的功能设定是借阅图书,而Return类的功能设定是归还图书。由于两者代码逻辑高度相似,故为了避免重复啰嗦,于是我将这两个类放在一起讲解。
在图书馆里系统中,无论是借阅还是归还,只需修改其书籍借阅状态即可,在本系统中我还添加了书籍借阅次数,所以在每次借阅成功之后,借阅次数需要+1。
代码实现如下:
Borrow类(借阅图书)
Return类(归还图书) 控制台输出示例如下:
(借阅)
(归还)
(5)Find类
Find类的功能设定为查找图书,逻辑较为简单。
代码实现如下:![](https://img-blog.csdnimg.cn/direct/3d03a22e4726487ca5a57458a55c1249.png)
控制台输出示例如下:
(6)Modify类
Modify类的功能设定为修改指定下标元素的信息。
代码实现如下:
控制台输出示例如下:
(7)Top类
Top类的功能设定为图书借阅次数排行榜,但是由于作者还未学习数据库相关知识,暂时不能实现代码持久化,故借阅次数会随着程序的关闭而清除,请您见谅...
代码实现如下:![](https://img-blog.csdnimg.cn/direct/3ba005953a374c0bab7590ebc051f89e.png)
控制台输出示例如下:
(8)Exit类
在mian方法中,当我们输入零时,便会结束运行本次程序。在结束之前,还会运行Exit类中的work方法,目前我仅设置其功能为 输出提示。
代码实现如下:
本系统目前只是初具雏形,在以后,我会随着自己技术的提升不断对该系统进行优化,希望这一天能够尽快到来! 感谢大家的观看,希望这篇文章能让您有所收获!
版权归原作者 careathers 所有, 如有侵权,请联系我们删除。