一个功能齐全的JAVA 实例:图书管理

本文介绍了一个用Java实现的图书馆模拟系统,包括创建图书、创建读者、借书、还书等功能。通过内部类的设计,简化了命令处理流程,提高了程序的可扩展性。

用 Java 模拟一个图书馆。包括创建图书、创建读者、借书、还书、列出所有图书、列出所有读者、列出已借出的图书、列出过期未还的图书等功能。每个读者最多只能借 3 本书,每个书最多只能借 3 个星期,超过就算过期。

下面是一个命令行下的实现。这个例子的主要目的是向初学者展示内部类的好处。Command 及其子类都是 LibrarySimulator 的内部类。它们可以无阻碍的访问 LibrarySimulator 的成员。使用内部类,而不是大量的 if-else,让程序更容易扩展。

  1. importjava.io.BufferedReader;
  2. importjava.io.IOException;
  3. importjava.io.InputStreamReader;
  4. importjava.text.SimpleDateFormat;
  5. importjava.util.*;
  6. /**
  7. *一个图书馆的课程设计。主要功能:
  8. *1.创建图书
  9. *2.创建读者
  10. *3.借书
  11. *4.还书
  12. *5.列出所有书
  13. *6.列出已借书
  14. *7.列出超过日期未还的书
  15. */
  16. publicclassLibrarySimulator{
  17. //主菜单
  18. privatestaticfinalStringMAIN_MENU="1.列出所有的书/n"+
  19. "2.列出已借出的书/n"+
  20. "3.列出过期未还的书/n"+
  21. "4.列出所有读者/n"+
  22. "5.创建图书/n"+
  23. "6.创建读者/n"+
  24. "7.借书/n"+
  25. "8.还书/n"+
  26. "9.退出/n"+
  27. "请输入序号:";
  28. //选择图书类型的菜单。在借书和添加图书的时候都会用到
  29. privatestaticfinalStringTYPE_MENU;
  30. //表示一个数字的正则表达式
  31. privatestaticfinalStringDIGIT_CHOICE_PATTERN="^//d$";
  32. //表示非空字符串
  33. privatestaticfinalStringNOT_EMPTY_PATTERN="//S.*";
  34. //日期格式
  35. staticfinalStringDATE_PATTERN="yyyy/MM/dd";
  36. //验证用户输入日期的正则表达式
  37. staticfinalStringDATE_FORMAT_PATTERN="^//d{4}///d{2}///d{2}$";
  38. //预定义的图书类型
  39. staticHashMap<String,String>TYPES=newLinkedHashMap<String,String>();
  40. static{
  41. TYPES.put("1","科学类");
  42. TYPES.put("2","文学类");//新的类别可以继续在后面添加
  43. TYPE_MENU=createTypeMenu();
  44. }
  45. //生成选择类别的菜单
  46. privatestaticStringcreateTypeMenu(){
  47. Stringstr="";
  48. for(Stringindex:TYPES.keySet()){
  49. str+=index+"."+TYPES.get(index)+"/n";
  50. }
  51. returnstr+"请选择书的类型:";
  52. }
  53. privateHashMap<Integer,Command>commands=newHashMap<Integer,Command>();
  54. privateArrayList<Book>books=newArrayList<Book>();
  55. privateArrayList<Reader>readers=newArrayList<Reader>();
  56. //程序入口。这里创建一个LibrarySimulator用于模拟界面。
  57. publicstaticvoidmain(String[]args){
  58. newLibrarySimulator().start();
  59. }
  60. /**
  61. *构造函数
  62. */
  63. publicLibrarySimulator(){
  64. commands.put(1,newCommand1());
  65. commands.put(2,newCommand2());
  66. commands.put(3,newCommand3());
  67. commands.put(4,newCommand4());
  68. commands.put(5,newCommand5());
  69. commands.put(6,newCommand6());
  70. commands.put(7,newCommand7());
  71. commands.put(8,newCommand8());
  72. }
  73. /**
  74. *这里接受用户输入,执行操作,然后再等待用户输入,这样不停的循环。
  75. */
  76. privatevoidstart(){
  77. Stringindex=prompt(MAIN_MENU,DIGIT_CHOICE_PATTERN);
  78. while(!index.equals("9")){
  79. executeCommand(index);
  80. index=prompt(MAIN_MENU,DIGIT_CHOICE_PATTERN);
  81. }
  82. }
  83. //根据序号执行命令
  84. privatevoidexecuteCommand(Stringindex){
  85. Commandcommand=commands.get(Integer.parseInt(index));
  86. if(command!=null){
  87. Stringresult=command.execute();
  88. System.out.println(result+"/n");
  89. }
  90. }
  91. //打印一条提示信息,然后读取并返回用户输入
  92. privateStringprompt(Stringmessage,Stringpattern){
  93. System.out.print(message);
  94. if(pattern==null){
  95. returnreadInput();
  96. }else{
  97. Stringresult="";
  98. while(!result.matches(pattern)){
  99. result=readInput();
  100. }
  101. returnresult;
  102. }
  103. }
  104. //读取用户输入
  105. privateStringreadInput(){
  106. try{
  107. BufferedReaderreader=newBufferedReader(newInputStreamReader(System.in));
  108. returnreader.readLine();
  109. }catch(IOExceptione){
  110. e.printStackTrace();
  111. return"";
  112. }
  113. }
  114. //根据名字查找读者。找不到则返回null。
  115. privateReadergetReaderByName(StringreaderName){
  116. for(Readerreader:readers){
  117. if(reader.getName().equals(readerName)){
  118. returnreader;
  119. }
  120. }
  121. returnnull;
  122. }
  123. //根据名字查找图书。找不到则返回null。
  124. privateBookgetBookByName(StringbookName){
  125. for(Bookbook:books){
  126. if(book.getName().equals(bookName)){
  127. returnbook;
  128. }
  129. }
  130. returnnull;
  131. }
  132. /*===================================================================*/
  133. /**
  134. *代表命令的抽象类
  135. */
  136. privateabstractclassCommand{
  137. protectedabstractStringexecute();
  138. }
  139. ///////////////////////////////////////////////////列出所有图书
  140. privateclassCommand1extendsCommand{
  141. protectedStringexecute(){
  142. for(Bookbook:getBooks()){
  143. System.out.println(book);//这里会自动调用book.toString()
  144. }
  145. return"命令完成。";
  146. }
  147. privateArrayList<Book>getBooks(){
  148. ArrayList<Book>result=newArrayList<Book>();
  149. for(Bookbook:books){
  150. if(isValid(book)){
  151. result.add(book);
  152. }
  153. }
  154. returnresult;
  155. }
  156. //考虑到第1、2、3条命令大体相同,这里提供了一个给子类覆写的方法
  157. protectedbooleanisValid(Bookbook){
  158. returntrue;
  159. }
  160. }
  161. /////////////////////////////////////////////////////列出已借出的书。
  162. //注意它的父类不是Command,而是Command1。这样节省了很多重复代码
  163. privateclassCommand2extendsCommand1{
  164. @Override
  165. protectedbooleanisValid(Bookbook){
  166. returnbook.isBorrowed();
  167. }
  168. }
  169. ////////////////////////////////////////////////////////列出过期未还的书
  170. privateclassCommand3extendsCommand1{
  171. @Override
  172. protectedbooleanisValid(Bookbook){
  173. //判断一本书接触过期与否的方法最好在Book类中去实现。
  174. returnbook.isExpired();
  175. }
  176. }
  177. ///////////////////////////////////////////////创建图书
  178. privateclassCommand5extendsCommand{
  179. protectedStringexecute(){
  180. Stringtype=getType();
  181. Stringname=getName();
  182. if(getBookByName(name)==null){
  183. books.add(newBook(type,name));
  184. return"图书添加成功。";
  185. }else{
  186. return"图书添加失败:名称已存在。";
  187. }
  188. }
  189. //获得用户输入的书名
  190. privateStringgetName(){
  191. returnprompt("请输入书名:",NOT_EMPTY_PATTERN);
  192. }
  193. //获得用户选择的图书类型
  194. privateStringgetType(){
  195. returnprompt(TYPE_MENU,DIGIT_CHOICE_PATTERN);
  196. }
  197. }
  198. ///////////////////////////////////////////////////////列出所有读者
  199. privateclassCommand4extendsCommand{
  200. protectedStringexecute(){
  201. for(Readerreader:readers){
  202. System.out.println(reader);
  203. }
  204. return"命令完成。";
  205. }
  206. }
  207. ///////////////////////////////////////////////////////创建读者
  208. privateclassCommand6extendsCommand{
  209. protectedStringexecute(){
  210. Stringname=getName();
  211. if(getReaderByName(name)==null){
  212. readers.add(newReader(name));
  213. return"读者创建成功。";
  214. }else{
  215. return"读者创建失败:名字已经存在。";
  216. }
  217. }
  218. publicStringgetName(){
  219. returnprompt("请输入读者名字:",NOT_EMPTY_PATTERN);
  220. }
  221. }
  222. ///////////////////////////////////////////////////////借书
  223. privateclassCommand7extendsCommand{
  224. protectedStringexecute(){
  225. Readerreader=getReader();
  226. if(reader==null){
  227. System.out.println("命令取消。");
  228. return"";
  229. }
  230. Bookbook=getBook();
  231. if(book==null){
  232. System.out.println("命令取消。");
  233. return"";
  234. }
  235. StringborrowDate=getBorrowDate();
  236. book.borrowBy(reader.getName(),borrowDate);
  237. reader.addBorrowCount();
  238. return"成功借出。";
  239. }
  240. privateStringgetBorrowDate(){
  241. Stringnow=newSimpleDateFormat(LibrarySimulator.DATE_PATTERN).format(newDate());
  242. Stringdate=null;
  243. while(date==null||!date.matches(DATE_FORMAT_PATTERN)){
  244. date=prompt("请输入结束日期(如"+now+")",NOT_EMPTY_PATTERN);
  245. }
  246. returndate;
  247. }
  248. privateBookgetBook(){
  249. Bookbook=null;
  250. while(book==null||book.isBorrowed()){
  251. StringbookName=prompt("请输入图书名字:",null);
  252. if(bookName.equals("")){
  253. returnnull;
  254. }
  255. book=getBookByName(bookName);
  256. if(book==null){
  257. System.out.println("图书不存在。");
  258. }elseif(book.isBorrowed()){
  259. System.out.println("图书已经被借出。");
  260. }
  261. }
  262. returnbook;
  263. }
  264. privateReadergetReader(){
  265. Readerreader=null;
  266. while(reader==null||!reader.canBorrow()){
  267. StringreaderName=prompt("请输入读者名字:",null);
  268. if(readerName.equals("")){
  269. returnnull;
  270. }
  271. reader=getReaderByName(readerName);
  272. if(reader==null){
  273. System.out.println("读者不存在。");
  274. }elseif(!reader.canBorrow()){
  275. System.out.println("该读者已经借了"+Reader.MAX_BORROW+"本书,不能继续借了。");
  276. }
  277. }
  278. returnreader;
  279. }
  280. }
  281. /////////////////////////////////////////////还书
  282. privateclassCommand8extendsCommand{
  283. protectedStringexecute(){
  284. Readerreader=getReader();
  285. if(reader==null){
  286. System.out.println("命令取消。");
  287. return"";
  288. }
  289. Bookbook=getBook(reader);
  290. if(book==null){
  291. System.out.println("命令取消。");
  292. return"";
  293. }
  294. reader.reduceBorrowCount();
  295. book.returned();
  296. return"操作成功。";
  297. }
  298. privateBookgetBook(Readerreader){
  299. Bookbook=null;
  300. while(book==null||!reader.getName().equals(book.getBorrower())){
  301. StringbookName=prompt("请输入图书名字:",null);
  302. if(bookName.equals("")){
  303. returnnull;
  304. }
  305. book=getBookByName(bookName);
  306. if(book==null){
  307. System.out.println("图书不存在。");
  308. }elseif(!reader.getName().equals(book.getBorrower())){
  309. System.out.println("该读者没有借出这本书。");
  310. }
  311. }
  312. returnbook;
  313. }
  314. privateReadergetReader(){
  315. Readerreader=null;
  316. while(reader==null){
  317. StringreaderName=prompt("请输入读者名字:",null);
  318. if(readerName.equals("")){
  319. returnnull;
  320. }
  321. reader=getReaderByName(readerName);
  322. if(reader==null){
  323. System.out.println("读者不存在。");
  324. }
  325. }
  326. returnreader;
  327. }
  328. }
  329. }
  330. //图书
  331. classBook{
  332. publicstaticfinalintEXPIRE_DAYS=21;//可借出天数,超过就算过期
  333. privateStringtype;
  334. privateStringname;
  335. privateStringborrowedBy=null;
  336. privateStringborrowDate=null;
  337. Book(Stringtype,Stringname){
  338. this.type=type;
  339. this.name=name;
  340. }
  341. @Override
  342. publicStringtoString(){
  343. Stringstr=String.format("类别:%s书名:%s",LibrarySimulator.TYPES.get(type),name);
  344. if(isBorrowed()){
  345. str+="借出人:"+borrowedBy+"借出时间:"+borrowDate;
  346. }
  347. returnstr;
  348. }
  349. publicbooleanisBorrowed(){
  350. returnborrowedBy!=null;
  351. }
  352. publicStringgetName(){
  353. returnname;
  354. }
  355. publicStringgetBorrowDate(){
  356. returnborrowDate;
  357. }
  358. /**
  359. *图书借出
  360. *
  361. *@paramname读者名字
  362. *@paramdate借出日期。格式:参见{@linkLibrarySimulator#DATE_PATTERN}
  363. */
  364. publicvoidborrowBy(Stringname,Stringdate){
  365. this.borrowedBy=name;
  366. this.borrowDate=date;
  367. }
  368. publicbooleanisExpired(){
  369. if(borrowDate==null){
  370. returnfalse;//没有借出的书不出现在过期未还列表当中,所以这里返回false。
  371. }
  372. //从当前时间往前推3个星期,如果还在借书日期之后,说明借书已经超过3个星期了
  373. StringthreeWksAgo=get3WeeksAgo();
  374. returnthreeWksAgo.compareTo(borrowDate)>0;
  375. }
  376. //获得3个星期前的日期
  377. privateStringget3WeeksAgo(){
  378. SimpleDateFormatf=newSimpleDateFormat(LibrarySimulator.DATE_PATTERN);
  379. Calendarc=Calendar.getInstance();
  380. c.add(Calendar.DAY_OF_MONTH,-EXPIRE_DAYS);
  381. returnf.format(c.getTime());
  382. }
  383. publicvoidreturned(){
  384. this.borrowBy(null,null);
  385. }
  386. publicStringgetBorrower(){
  387. returnborrowedBy;
  388. }
  389. }
  390. //读者
  391. classReader{
  392. //每位读者最多可同时借出3本书
  393. publicstaticfinalintMAX_BORROW=3;
  394. privateStringname;
  395. privateintborowCount=0;
  396. publicintgetBorowCount(){
  397. returnborowCount;
  398. }
  399. Reader(Stringname){
  400. this.name=name;
  401. }
  402. publicStringgetName(){
  403. returnname;
  404. }
  405. publicvoidaddBorrowCount(){
  406. borowCount++;
  407. }
  408. publicvoidreduceBorrowCount(){
  409. borowCount--;
  410. }
  411. publicbooleancanBorrow(){
  412. returnborowCount<MAX_BORROW;
  413. }
  414. @Override
  415. publicStringtoString(){
  416. returnname;
  417. }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值