Java小例子:图书馆课程设计

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

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

01.import java.io.BufferedReader;02.import java.io.IOException;03.import java.io.InputStreamReader;04.import java.text.SimpleDateFormat;05.import java.util.*;06.07./**08. * 一个图书馆的课程设计。主要功能:09. * 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(1, new Command1());81.        commands.put(2, new Command2());82.        commands.put(3, new Command3());83.        commands.put(4, new Command4());84.        commands.put(5, new Command5());85.        commands.put(6, new Command6());86.        commands.put(7, new Command7());87.        commands.put(8, new 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.        @Override198.        protected boolean isValid(Book book) {199.            return book.isBorrowed();200.        }201.    }202.203.    //////////////////////////////////////////////////////// 列出过期未还的书204.    private class Command3 extends Command1 {205.206.        @Override207.        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.    @Override413.    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(null, null);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.    @Override506.    public String toString() {507.        return name;508.    }509.} 

送给中意的TA,背面写上:某年某月某日,

Java小例子:图书馆课程设计

相关文章:

你感兴趣的文章:

标签云: