用 Java 模拟一个图书馆。包括创建图书、创建读者、借书、还书、列出所有图书、列出所有读者、列出已借出的图书、列出过期未还的图书等功能。每个读者最多只能借 3 本书,每个书最多只能借 3 个星期,超过就算过期。
下面是一个命令行下的实现。这个例子的主要目的是向初学者展示内部类的好处。Command 及其子类都是 LibrarySimulator 的内部类。它们可以无阻碍的访问 LibrarySimulator 的成员。使用内部类,而不是大量的 if-else,让程序更容易扩展。
- importjava.io.BufferedReader;
- importjava.io.IOException;
- importjava.io.InputStreamReader;
- importjava.text.SimpleDateFormat;
- importjava.util.*;
- /**
- *一个图书馆的课程设计。主要功能:
- *1.创建图书
- *2.创建读者
- *3.借书
- *4.还书
- *5.列出所有书
- *6.列出已借书
- *7.列出超过日期未还的书
- */
- publicclassLibrarySimulator{
- //主菜单
- privatestaticfinalStringMAIN_MENU="1.列出所有的书/n"+
- "2.列出已借出的书/n"+
- "3.列出过期未还的书/n"+
- "4.列出所有读者/n"+
- "5.创建图书/n"+
- "6.创建读者/n"+
- "7.借书/n"+
- "8.还书/n"+
- "9.退出/n"+
- "请输入序号:";
- //选择图书类型的菜单。在借书和添加图书的时候都会用到
- privatestaticfinalStringTYPE_MENU;
- //表示一个数字的正则表达式
- privatestaticfinalStringDIGIT_CHOICE_PATTERN="^//d$";
- //表示非空字符串
- privatestaticfinalStringNOT_EMPTY_PATTERN="//S.*";
- //日期格式
- staticfinalStringDATE_PATTERN="yyyy/MM/dd";
- //验证用户输入日期的正则表达式
- staticfinalStringDATE_FORMAT_PATTERN="^//d{4}///d{2}///d{2}$";
- //预定义的图书类型
- staticHashMap<String,String>TYPES=newLinkedHashMap<String,String>();
- static{
- TYPES.put("1","科学类");
- TYPES.put("2","文学类");//新的类别可以继续在后面添加
- TYPE_MENU=createTypeMenu();
- }
- //生成选择类别的菜单
- privatestaticStringcreateTypeMenu(){
- Stringstr="";
- for(Stringindex:TYPES.keySet()){
- str+=index+"."+TYPES.get(index)+"/n";
- }
- returnstr+"请选择书的类型:";
- }
- privateHashMap<Integer,Command>commands=newHashMap<Integer,Command>();
- privateArrayList<Book>books=newArrayList<Book>();
- privateArrayList<Reader>readers=newArrayList<Reader>();
- //程序入口。这里创建一个LibrarySimulator用于模拟界面。
- publicstaticvoidmain(String[]args){
- newLibrarySimulator().start();
- }
- /**
- *构造函数
- */
- publicLibrarySimulator(){
- commands.put(1,newCommand1());
- commands.put(2,newCommand2());
- commands.put(3,newCommand3());
- commands.put(4,newCommand4());
- commands.put(5,newCommand5());
- commands.put(6,newCommand6());
- commands.put(7,newCommand7());
- commands.put(8,newCommand8());
- }
- /**
- *这里接受用户输入,执行操作,然后再等待用户输入,这样不停的循环。
- */
- privatevoidstart(){
- Stringindex=prompt(MAIN_MENU,DIGIT_CHOICE_PATTERN);
- while(!index.equals("9")){
- executeCommand(index);
- index=prompt(MAIN_MENU,DIGIT_CHOICE_PATTERN);
- }
- }
- //根据序号执行命令
- privatevoidexecuteCommand(Stringindex){
- Commandcommand=commands.get(Integer.parseInt(index));
- if(command!=null){
- Stringresult=command.execute();
- System.out.println(result+"/n");
- }
- }
- //打印一条提示信息,然后读取并返回用户输入
- privateStringprompt(Stringmessage,Stringpattern){
- System.out.print(message);
- if(pattern==null){
- returnreadInput();
- }else{
- Stringresult="";
- while(!result.matches(pattern)){
- result=readInput();
- }
- returnresult;
- }
- }
- //读取用户输入
- privateStringreadInput(){
- try{
- BufferedReaderreader=newBufferedReader(newInputStreamReader(System.in));
- returnreader.readLine();
- }catch(IOExceptione){
- e.printStackTrace();
- return"";
- }
- }
- //根据名字查找读者。找不到则返回null。
- privateReadergetReaderByName(StringreaderName){
- for(Readerreader:readers){
- if(reader.getName().equals(readerName)){
- returnreader;
- }
- }
- returnnull;
- }
- //根据名字查找图书。找不到则返回null。
- privateBookgetBookByName(StringbookName){
- for(Bookbook:books){
- if(book.getName().equals(bookName)){
- returnbook;
- }
- }
- returnnull;
- }
- /*===================================================================*/
- /**
- *代表命令的抽象类
- */
- privateabstractclassCommand{
- protectedabstractStringexecute();
- }
- ///////////////////////////////////////////////////列出所有图书
- privateclassCommand1extendsCommand{
- protectedStringexecute(){
- for(Bookbook:getBooks()){
- System.out.println(book);//这里会自动调用book.toString()
- }
- return"命令完成。";
- }
- privateArrayList<Book>getBooks(){
- ArrayList<Book>result=newArrayList<Book>();
- for(Bookbook:books){
- if(isValid(book)){
- result.add(book);
- }
- }
- returnresult;
- }
- //考虑到第1、2、3条命令大体相同,这里提供了一个给子类覆写的方法
- protectedbooleanisValid(Bookbook){
- returntrue;
- }
- }
- /////////////////////////////////////////////////////列出已借出的书。
- //注意它的父类不是Command,而是Command1。这样节省了很多重复代码
- privateclassCommand2extendsCommand1{
- @Override
- protectedbooleanisValid(Bookbook){
- returnbook.isBorrowed();
- }
- }
- ////////////////////////////////////////////////////////列出过期未还的书
- privateclassCommand3extendsCommand1{
- @Override
- protectedbooleanisValid(Bookbook){
- //判断一本书接触过期与否的方法最好在Book类中去实现。
- returnbook.isExpired();
- }
- }
- ///////////////////////////////////////////////创建图书
- privateclassCommand5extendsCommand{
- protectedStringexecute(){
- Stringtype=getType();
- Stringname=getName();
- if(getBookByName(name)==null){
- books.add(newBook(type,name));
- return"图书添加成功。";
- }else{
- return"图书添加失败:名称已存在。";
- }
- }
- //获得用户输入的书名
- privateStringgetName(){
- returnprompt("请输入书名:",NOT_EMPTY_PATTERN);
- }
- //获得用户选择的图书类型
- privateStringgetType(){
- returnprompt(TYPE_MENU,DIGIT_CHOICE_PATTERN);
- }
- }
- ///////////////////////////////////////////////////////列出所有读者
- privateclassCommand4extendsCommand{
- protectedStringexecute(){
- for(Readerreader:readers){
- System.out.println(reader);
- }
- return"命令完成。";
- }
- }
- ///////////////////////////////////////////////////////创建读者
- privateclassCommand6extendsCommand{
- protectedStringexecute(){
- Stringname=getName();
- if(getReaderByName(name)==null){
- readers.add(newReader(name));
- return"读者创建成功。";
- }else{
- return"读者创建失败:名字已经存在。";
- }
- }
- publicStringgetName(){
- returnprompt("请输入读者名字:",NOT_EMPTY_PATTERN);
- }
- }
- ///////////////////////////////////////////////////////借书
- privateclassCommand7extendsCommand{
- protectedStringexecute(){
- Readerreader=getReader();
- if(reader==null){
- System.out.println("命令取消。");
- return"";
- }
- Bookbook=getBook();
- if(book==null){
- System.out.println("命令取消。");
- return"";
- }
- StringborrowDate=getBorrowDate();
- book.borrowBy(reader.getName(),borrowDate);
- reader.addBorrowCount();
- return"成功借出。";
- }
- privateStringgetBorrowDate(){
- Stringnow=newSimpleDateFormat(LibrarySimulator.DATE_PATTERN).format(newDate());
- Stringdate=null;
- while(date==null||!date.matches(DATE_FORMAT_PATTERN)){
- date=prompt("请输入结束日期(如"+now+")",NOT_EMPTY_PATTERN);
- }
- returndate;
- }
- privateBookgetBook(){
- Bookbook=null;
- while(book==null||book.isBorrowed()){
- StringbookName=prompt("请输入图书名字:",null);
- if(bookName.equals("")){
- returnnull;
- }
- book=getBookByName(bookName);
- if(book==null){
- System.out.println("图书不存在。");
- }elseif(book.isBorrowed()){
- System.out.println("图书已经被借出。");
- }
- }
- returnbook;
- }
- privateReadergetReader(){
- Readerreader=null;
- while(reader==null||!reader.canBorrow()){
- StringreaderName=prompt("请输入读者名字:",null);
- if(readerName.equals("")){
- returnnull;
- }
- reader=getReaderByName(readerName);
- if(reader==null){
- System.out.println("读者不存在。");
- }elseif(!reader.canBorrow()){
- System.out.println("该读者已经借了"+Reader.MAX_BORROW+"本书,不能继续借了。");
- }
- }
- returnreader;
- }
- }
- /////////////////////////////////////////////还书
- privateclassCommand8extendsCommand{
- protectedStringexecute(){
- Readerreader=getReader();
- if(reader==null){
- System.out.println("命令取消。");
- return"";
- }
- Bookbook=getBook(reader);
- if(book==null){
- System.out.println("命令取消。");
- return"";
- }
- reader.reduceBorrowCount();
- book.returned();
- return"操作成功。";
- }
- privateBookgetBook(Readerreader){
- Bookbook=null;
- while(book==null||!reader.getName().equals(book.getBorrower())){
- StringbookName=prompt("请输入图书名字:",null);
- if(bookName.equals("")){
- returnnull;
- }
- book=getBookByName(bookName);
- if(book==null){
- System.out.println("图书不存在。");
- }elseif(!reader.getName().equals(book.getBorrower())){
- System.out.println("该读者没有借出这本书。");
- }
- }
- returnbook;
- }
- privateReadergetReader(){
- Readerreader=null;
- while(reader==null){
- StringreaderName=prompt("请输入读者名字:",null);
- if(readerName.equals("")){
- returnnull;
- }
- reader=getReaderByName(readerName);
- if(reader==null){
- System.out.println("读者不存在。");
- }
- }
- returnreader;
- }
- }
- }
- //图书
- classBook{
- publicstaticfinalintEXPIRE_DAYS=21;//可借出天数,超过就算过期
- privateStringtype;
- privateStringname;
- privateStringborrowedBy=null;
- privateStringborrowDate=null;
- Book(Stringtype,Stringname){
- this.type=type;
- this.name=name;
- }
- @Override
- publicStringtoString(){
- Stringstr=String.format("类别:%s书名:%s",LibrarySimulator.TYPES.get(type),name);
- if(isBorrowed()){
- str+="借出人:"+borrowedBy+"借出时间:"+borrowDate;
- }
- returnstr;
- }
- publicbooleanisBorrowed(){
- returnborrowedBy!=null;
- }
- publicStringgetName(){
- returnname;
- }
- publicStringgetBorrowDate(){
- returnborrowDate;
- }
- /**
- *图书借出
- *
- *@paramname读者名字
- *@paramdate借出日期。格式:参见{@linkLibrarySimulator#DATE_PATTERN}
- */
- publicvoidborrowBy(Stringname,Stringdate){
- this.borrowedBy=name;
- this.borrowDate=date;
- }
- publicbooleanisExpired(){
- if(borrowDate==null){
- returnfalse;//没有借出的书不出现在过期未还列表当中,所以这里返回false。
- }
- //从当前时间往前推3个星期,如果还在借书日期之后,说明借书已经超过3个星期了
- StringthreeWksAgo=get3WeeksAgo();
- returnthreeWksAgo.compareTo(borrowDate)>0;
- }
- //获得3个星期前的日期
- privateStringget3WeeksAgo(){
- SimpleDateFormatf=newSimpleDateFormat(LibrarySimulator.DATE_PATTERN);
- Calendarc=Calendar.getInstance();
- c.add(Calendar.DAY_OF_MONTH,-EXPIRE_DAYS);
- returnf.format(c.getTime());
- }
- publicvoidreturned(){
- this.borrowBy(null,null);
- }
- publicStringgetBorrower(){
- returnborrowedBy;
- }
- }
- //读者
- classReader{
- //每位读者最多可同时借出3本书
- publicstaticfinalintMAX_BORROW=3;
- privateStringname;
- privateintborowCount=0;
- publicintgetBorowCount(){
- returnborowCount;
- }
- Reader(Stringname){
- this.name=name;
- }
- publicStringgetName(){
- returnname;
- }
- publicvoidaddBorrowCount(){
- borowCount++;
- }
- publicvoidreduceBorrowCount(){
- borowCount--;
- }
- publicbooleancanBorrow(){
- returnborowCount<MAX_BORROW;
- }
- @Override
- publicStringtoString(){
- returnname;
- }
本文介绍了一个用Java实现的图书馆模拟系统,包括创建图书、创建读者、借书、还书等功能。通过内部类的设计,简化了命令处理流程,提高了程序的可扩展性。
2061

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



