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

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

 

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

  1. import java.io.BufferedReader;   
  2. import java.io.IOException;   
  3. import java.io.InputStreamReader;   
  4. import java.text.SimpleDateFormat;   
  5. import java.util.*;   
  6.     
  7. /**  
  8.  * 一个图书馆的课程设计。主要功能:  
  9.  * 1. 创建图书  
  10.  * 2. 创建读者  
  11.  * 3. 借书  
  12.  * 4. 还书  
  13.  * 5. 列出所有书  
  14.  * 6. 列出已借书  
  15.  * 7. 列出超过日期未还的书  
  16.  */  
  17. public class LibrarySimulator {   
  18.     
  19.     // 主菜单   
  20.     private static final String MAIN_MENU = "1. 列出所有的书/n" +   
  21.             "2. 列出已借出的书/n" +   
  22.             "3. 列出过期未还的书/n" +   
  23.             "4. 列出所有读者/n" +   
  24.             "5. 创建图书/n" +   
  25.             "6. 创建读者/n" +   
  26.             "7. 借书/n" +   
  27.             "8. 还书/n" +   
  28.             "9. 退出/n" +   
  29.             "请输入序号:";   
  30.     
  31.     // 选择图书类型的菜单。在借书和添加图书的时候都会用到   
  32.     private static final String TYPE_MENU;   
  33.     
  34.     // 表示一个数字的正则表达式   
  35.     private static final String DIGIT_CHOICE_PATTERN = "^//d$";   
  36.     
  37.     // 表示非空字符串   
  38.     private static final String NOT_EMPTY_PATTERN = "//S.*";   
  39.     
  40.     // 日期格式   
  41.     static final String DATE_PATTERN = "yyyy/MM/dd";   
  42.     
  43.     // 验证用户输入日期的正则表达式   
  44.     static final String DATE_FORMAT_PATTERN = "^//d{4}///d{2}///d{2}$";   
  45.     
  46.     // 预定义的图书类型   
  47.     static HashMap<String, String> TYPES = new LinkedHashMap<String, String>();   
  48.     
  49.     static {   
  50.         TYPES.put("1""科学类");   
  51.         TYPES.put("2""文学类");  // 新的类别可以继续在后面添加   
  52.         TYPE_MENU = createTypeMenu();   
  53.     }   
  54.     
  55.     // 生成选择类别的菜单   
  56.     private static String createTypeMenu() {   
  57.         String str = "";   
  58.         for (String index : TYPES.keySet()) {   
  59.             str += index + ". " + TYPES.get(index) + "/n";   
  60.         }   
  61.         return str + "请选择书的类型:";   
  62.     }   
  63.     
  64.     
  65.     private HashMap<Integer, Command> commands = new HashMap<Integer, Command>();   
  66.     
  67.     private ArrayList<Book> books = new ArrayList<Book>();   
  68.     
  69.     private ArrayList<Reader> readers = new ArrayList<Reader>();   
  70.     
  71.     // 程序入口。这里创建一个 LibrarySimulator 用于模拟界面。   
  72.     public static void main(String[] args) {   
  73.         new LibrarySimulator().start();   
  74.     }   
  75.     
  76.     /**  
  77.      * 构造函数  
  78.      */  
  79.     public LibrarySimulator() {   
  80.         commands.put(1new Command1());   
  81.         commands.put(2new Command2());   
  82.         commands.put(3new Command3());   
  83.         commands.put(4new Command4());   
  84.         commands.put(5new Command5());   
  85.         commands.put(6new Command6());   
  86.         commands.put(7new Command7());   
  87.         commands.put(8new Command8());   
  88.     }   
  89.     
  90.     /**  
  91.      * 这里接受用户输入,执行操作,然后再等待用户输入,这样不停的循环。  
  92.      */  
  93.     private void start() {   
  94.         String index = prompt(MAIN_MENU, DIGIT_CHOICE_PATTERN);   
  95.     
  96.         while (!index.equals("9")) {   
  97.             executeCommand(index);   
  98.             index = prompt(MAIN_MENU, DIGIT_CHOICE_PATTERN);   
  99.         }   
  100.     }   
  101.     
  102.     // 根据序号执行命令   
  103.     private void executeCommand(String index) {   
  104.         Command command = commands.get(Integer.parseInt(index));   
  105.         if (command != null) {   
  106.             String result = command.execute();   
  107.             System.out.println(result + "/n");   
  108.         }   
  109.     }   
  110.     
  111.     // 打印一条提示信息,然后读取并返回用户输入   
  112.     private String prompt(String message, String pattern) {   
  113.         System.out.print(message);   
  114.         if (pattern == null) {   
  115.             return readInput();   
  116.         } else {   
  117.             String result = "";   
  118.             while (!result.matches(pattern)) {   
  119.                 result = readInput();   
  120.             }   
  121.             return result;   
  122.         }   
  123.     }   
  124.     
  125.     // 读取用户输入   
  126.     private String readInput() {   
  127.         try {   
  128.             BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));   
  129.             return reader.readLine();   
  130.         } catch (IOException e) {   
  131.             e.printStackTrace();   
  132.             return "";   
  133.         }   
  134.     }   
  135.     
  136.     // 根据名字查找读者。找不到则返回 null。   
  137.     private Reader getReaderByName(String readerName) {   
  138.         for (Reader reader : readers) {   
  139.             if (reader.getName().equals(readerName)) {   
  140.                 return reader;   
  141.             }   
  142.         }   
  143.         return null;   
  144.     }   
  145.     
  146.     // 根据名字查找图书。找不到则返回 null。   
  147.     private Book getBookByName(String bookName) {   
  148.         for (Book book : books) {   
  149.             if (book.getName().equals(bookName)) {   
  150.                 return book;   
  151.             }   
  152.         }   
  153.         return null;   
  154.     }   
  155.     
  156.     /*===================================================================*/  
  157.     
  158.     /**  
  159.      * 代表命令的抽象类  
  160.      */  
  161.     private abstract class Command {   
  162.     
  163.         protected abstract String execute();   
  164.     }   
  165.     
  166.     /// 列出所有图书   
  167.     private class Command1 extends Command {   
  168.     
  169.         protected String execute() {   
  170.             for (Book book : getBooks()) {   
  171.                 System.out.println(book);   // 这里会自动调用 book.toString()   
  172.             }   
  173.             return "命令完成。";   
  174.         }   
  175.     
  176.         private ArrayList<Book> getBooks() {   
  177.             ArrayList<Book> result = new ArrayList<Book>();   
  178.     
  179.             for (Book book : books) {   
  180.                 if (isValid(book)) {   
  181.                     result.add(book);   
  182.                 }   
  183.             }   
  184.             return result;   
  185.         }   
  186.     
  187.         // 考虑到第 1、2、3 条命令大体相同,这里提供了一个给子类覆写的方法   
  188.         protected boolean isValid(Book book) {   
  189.             return true;   
  190.         }   
  191.     }   
  192.     
  193.     / 列出已借出的书。   
  194.     // 注意它的父类不是 Command,而是 Command1。这样节省了很多重复代码   
  195.     private class Command2 extends Command1 {   
  196.     
  197.         @Override  
  198.         protected boolean isValid(Book book) {   
  199.             return book.isBorrowed();   
  200.         }   
  201.     }   
  202.     
  203.      列出过期未还的书   
  204.     private class Command3 extends Command1 {   
  205.     
  206.         @Override  
  207.         protected boolean isValid(Book book) {   
  208.             // 判断一本书接触过期与否的方法最好在 Book 类中去实现。   
  209.             return book.isExpired();   
  210.         }   
  211.     }   
  212.     
  213.     /// 创建图书   
  214.     private class Command5 extends Command {   
  215.     
  216.         protected String execute() {   
  217.             String type = getType();   
  218.             String name = getName();   
  219.             if (getBookByName(name) == null) {   
  220.                 books.add(new Book(type, name));   
  221.                 return "图书添加成功。";   
  222.             } else {   
  223.                 return "图书添加失败:名称已存在。";   
  224.             }   
  225.         }   
  226.     
  227.         // 获得用户输入的书名   
  228.         private String getName() {   
  229.             return prompt("请输入书名:", NOT_EMPTY_PATTERN);   
  230.         }   
  231.     
  232.         // 获得用户选择的图书类型   
  233.         private String getType() {   
  234.             return prompt(TYPE_MENU, DIGIT_CHOICE_PATTERN);   
  235.         }   
  236.     }   
  237.     
  238.     /// 列出所有读者   
  239.     private class Command4 extends Command {   
  240.     
  241.         protected String execute() {   
  242.             for (Reader reader : readers) {   
  243.                 System.out.println(reader);   
  244.             }   
  245.             return "命令完成。";   
  246.         }   
  247.     }   
  248.     
  249.     /// 创建读者   
  250.     private class Command6 extends Command {   
  251.     
  252.         protected String execute() {   
  253.             String name = getName();   
  254.             if (getReaderByName(name) == null) {   
  255.                 readers.add(new Reader(name));   
  256.                 return "读者创建成功。";   
  257.             } else {   
  258.                 return "读者创建失败:名字已经存在。";   
  259.             }   
  260.         }   
  261.     
  262.         public String getName() {   
  263.             return prompt("请输入读者名字:", NOT_EMPTY_PATTERN);   
  264.         }   
  265.     }   
  266.     
  267.     /// 借书   
  268.     private class Command7 extends Command {   
  269.     
  270.         protected String execute() {   
  271.             Reader reader = getReader();   
  272.             if (reader == null) {   
  273.                 System.out.println("命令取消。");   
  274.                 return "";   
  275.             }   
  276.     
  277.             Book book = getBook();   
  278.             if (book == null) {   
  279.                 System.out.println("命令取消。");   
  280.                 return "";   
  281.             }   
  282.     
  283.             String borrowDate = getBorrowDate();   
  284.     
  285.             book.borrowBy(reader.getName(), borrowDate);   
  286.             reader.addBorrowCount();   
  287.     
  288.             return "成功借出。";   
  289.         }   
  290.     
  291.         private String getBorrowDate() {   
  292.             String now = new SimpleDateFormat(LibrarySimulator.DATE_PATTERN).format(new Date());   
  293.             String date = null;   
  294.             while (date == null || !date.matches(DATE_FORMAT_PATTERN)) {   
  295.                 date = prompt("请输入结束日期(如" + now + ")", NOT_EMPTY_PATTERN);   
  296.             }   
  297.             return date;   
  298.         }   
  299.     
  300.         private Book getBook() {   
  301.             Book book = null;   
  302.             while (book == null || book.isBorrowed()) {   
  303.                 String bookName = prompt("请输入图书名字:"null);   
  304.                 if (bookName.equals("")) {   
  305.                     return null;   
  306.                 }   
  307.     
  308.                 book = getBookByName(bookName);   
  309.                 if (book == null) {   
  310.                     System.out.println("图书不存在。");   
  311.                 } else if (book.isBorrowed()) {   
  312.                     System.out.println("图书已经被借出。");   
  313.                 }   
  314.             }   
  315.             return book;   
  316.         }   
  317.     
  318.         private Reader getReader() {   
  319.             Reader reader = null;   
  320.             while (reader == null || !reader.canBorrow()) {   
  321.                 String readerName = prompt("请输入读者名字:"null);   
  322.                 if (readerName.equals("")) {   
  323.                     return null;   
  324.                 }   
  325.     
  326.                 reader = getReaderByName(readerName);   
  327.                 if (reader == null) {   
  328.                     System.out.println("读者不存在。");   
  329.                 } else if (!reader.canBorrow()) {   
  330.                     System.out.println("该读者已经借了" + Reader.MAX_BORROW + " 本书,不能继续借了。");   
  331.                 }   
  332.             }   
  333.             return reader;   
  334.         }   
  335.     }   
  336.     
  337.     / 还书   
  338.     private class Command8 extends Command {   
  339.     
  340.         protected String execute() {   
  341.             Reader reader = getReader();   
  342.             if (reader == null) {   
  343.                 System.out.println("命令取消。");   
  344.                 return "";   
  345.             }   
  346.     
  347.             Book book = getBook(reader);   
  348.             if (book == null) {   
  349.                 System.out.println("命令取消。");   
  350.                 return "";   
  351.             }   
  352.     
  353.             reader.reduceBorrowCount();   
  354.             book.returned();   
  355.             return "操作成功。";   
  356.         }   
  357.     
  358.         private Book getBook(Reader reader) {   
  359.             Book book = null;   
  360.             while (book == null || !reader.getName().equals(book.getBorrower())) {   
  361.                 String bookName = prompt("请输入图书名字:"null);   
  362.                 if (bookName.equals("")) {   
  363.                     return null;   
  364.                 }   
  365.     
  366.                 book = getBookByName(bookName);   
  367.                 if (book == null) {   
  368.                     System.out.println("图书不存在。");   
  369.                 } else if (!reader.getName().equals(book.getBorrower())) {   
  370.                     System.out.println("该读者没有借出这本书。");   
  371.                 }   
  372.             }   
  373.             return book;   
  374.         }   
  375.     
  376.         private Reader getReader() {   
  377.             Reader reader = null;   
  378.             while (reader == null) {   
  379.                 String readerName = prompt("请输入读者名字:"null);   
  380.                 if (readerName.equals("")) {   
  381.                     return null;   
  382.                 }   
  383.     
  384.                 reader = getReaderByName(readerName);   
  385.                 if (reader == null) {   
  386.                     System.out.println("读者不存在。");   
  387.                 }   
  388.             }   
  389.             return reader;   
  390.         }   
  391.     }   
  392. }   
  393.     
  394. // 图书   
  395. class Book {   
  396.     
  397.     public static final int EXPIRE_DAYS = 21;   // 可借出天数,超过就算过期   
  398.     
  399.     private String type;   
  400.     
  401.     private String name;   
  402.     
  403.     private String borrowedBy = null;   
  404.     
  405.     private String borrowDate = null;   
  406.     
  407.     Book(String type, String name) {   
  408.         this.type = type;   
  409.         this.name = name;   
  410.     }   
  411.     
  412.     @Override  
  413.     public String toString() {   
  414.         String str = String.format("类别:%s  书名:%s", LibrarySimulator.TYPES.get(type), name);   
  415.         if (isBorrowed()) {   
  416.             str += "  借出人:" + borrowedBy + "  借出时间:" + borrowDate;   
  417.         }   
  418.         return str;   
  419.     }   
  420.     
  421.     public boolean isBorrowed() {   
  422.         return borrowedBy != null;   
  423.     }   
  424.     
  425.     public String getName() {   
  426.         return name;   
  427.     }   
  428.     
  429.     public String getBorrowDate() {   
  430.         return borrowDate;   
  431.     }   
  432.     
  433.     /**  
  434.      * 图书借出  
  435.      *  
  436.      * @param name 读者名字  
  437.      * @param date 借出日期。格式:参见 {@link LibrarySimulator#DATE_PATTERN}  
  438.      */  
  439.     public void borrowBy(String name, String date) {   
  440.         this.borrowedBy = name;   
  441.         this.borrowDate = date;   
  442.     }   
  443.     
  444.     public boolean isExpired() {   
  445.         if (borrowDate == null) {   
  446.             return false;   // 没有借出的书不出现在过期未还列表当中,所以这里返回 false。   
  447.         }   
  448.     
  449.         // 从当前时间往前推 3 个星期,如果还在借书日期之后,说明借书已经超过 3 个星期了   
  450.         String threeWksAgo = get3WeeksAgo();   
  451.         return threeWksAgo.compareTo(borrowDate) > 0;   
  452.     }   
  453.     
  454.     // 获得 3 个星期前的日期   
  455.     private String get3WeeksAgo() {   
  456.         SimpleDateFormat f = new SimpleDateFormat(LibrarySimulator.DATE_PATTERN);   
  457.         Calendar c = Calendar.getInstance();   
  458.         c.add(Calendar.DAY_OF_MONTH, -EXPIRE_DAYS);   
  459.         return f.format(c.getTime());   
  460.     }   
  461.     
  462.     public void returned() {   
  463.         this.borrowBy(nullnull);   
  464.     }   
  465.     
  466.     public String getBorrower() {   
  467.         return borrowedBy;   
  468.     }   
  469. }   
  470.     
  471. // 读者   
  472. class Reader {   
  473.     
  474.     // 每位读者最多可同时借出 3 本书   
  475.     public static final int MAX_BORROW = 3;   
  476.     
  477.     private String name;   
  478.     
  479.     private int borowCount = 0;   
  480.     
  481.     public int getBorowCount() {   
  482.         return borowCount;   
  483.     }   
  484.     
  485.     Reader(String name) {   
  486.         this.name = name;   
  487.     }   
  488.     
  489.     public String getName() {   
  490.         return name;   
  491.     }   
  492.     
  493.     public void addBorrowCount() {   
  494.         borowCount++;   
  495.     }   
  496.     
  497.     public void reduceBorrowCount() {   
  498.         borowCount--;   
  499.     }   
  500.     
  501.     public boolean canBorrow() {   
  502.         return borowCount < MAX_BORROW;   
  503.     }   
  504.     
  505.     @Override  
  506.     public String toString() {   
  507.         return name;   
  508.     }   

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值