Java 小例子:图书馆课程设计(Java 8 版)

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

这个例子跟http://blog.csdn.net/yidinghe/article/details/3940437 相比,增加了 Java 8 特有的语法,包括:Lambda 表达式,java.time 日期 API,streaming API 等。功能也比前者稍微完善了些,体积有所减小。

import java.time.LocalDate;import java.time.format.DateTimeFormatter;import java.time.temporal.ChronoUnit;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.Scanner;import java.util.concurrent.atomic.AtomicInteger;import java.util.function.Supplier;import java.util.stream.Collectors;/** * 图书馆例子 Java 8 版本 * created at 2014/11/4 * * @author Yiding */public class LibraryManager {    public static final Scanner SCANNER = new Scanner(System.in);    public static final String NUMBERS_ONLY = "^\\d+$"; // 表示只允许输入数字    public static final String ANY_CONTENT = "^\\S+$";  // 表示可以输入任何内容    public static void main(String[] args) {        new LibraryManager().start();    }    ////////////////////////////////////////////////////////////////    private Library library = new Library();    private ArrayList<Command> commands = new ArrayList<>();    private String mainMenu;    /**     * 构造方法     */    public LibraryManager() {        initCommands();        initStudents();        initBooks();    }    private void initBooks() {        this.library.addBook("论程序员的自我修养", "带鱼", BookType.科学类.toString());        this.library.addBook("印度四大名著全集", "阿达木", BookType.文学类.toString());        this.library.addBook("睡眠的好处", "程序员阿迪", BookType.科学类.toString());        this.library.addBook("架构师2014年10月刊", "美丽女人网", BookType.杂志.toString());    }    private void initStudents() {        this.library.students.add(new Student("张三"));        this.library.students.add(new Student("李四"));        this.library.students.add(new Student("王五"));    }    /**     * 初始化命令和主菜单     */    private void initCommands() {        addCommand(new ListCommand<>("所有图书:", () -> library.books), "查询所有图书");        addCommand(new ListCommand<>("所有学生:", () -> library.students), "查询所有学生");        addCommand(new AddBookCommand(), "添加图书");        addCommand(new DeleteBookCommand(), "删除图书");        addCommand(new BorrowBookCommand(), "借阅图书");        addCommand(new ReturnBookCommand(), "归还图书");        addCommand(new ListCommand<>("所有借阅过期的图书:", library::expiredBooks), "查询借阅过期的图书");        addCommand(new ExitCommand(), "退出");        this.mainMenu = toMenu("请输入命令", this.commands);    }    private void addCommand(Command command, String title) {        command.title = title;        this.commands.add(command);    }    /**     * 开始执行交互     */    private void start() {        CommandResult result;        // 在 while 条件中判断命令的执行结果是否表示要退出程序        // 只有 ExitCommand 的执行结果是 CommandResult.EXIT        do {            try {                String command = prompt(mainMenu, NUMBERS_ONLY); // 选择命令                result = executeCommand(command);                // 执行命令            } catch (CommandCancelException e) {                result = CommandResult.FAIL;            }            System.out.println(result.prompt + "\n");        } while (result != CommandResult.EXIT);    }    /**     * 打印一条提示消息并返回用户的输入     *     * @param prompt  提示消息     * @param pattern 指定格式,如果用户的输入不符合格式则会反复提示重新输入。为空则不检查用户输入     *     * @return 用户的输入     */    private String prompt(String prompt, String pattern) {        String userInput;        // 在 while 条件中判断用户输入的内容是否符合 pattern 指定的格式        // 如果 pattern 为 null 则不做判断        do {            System.out.print(prompt);            userInput = SCANNER.nextLine();            // 用户直接回车时,表示取消命令执行            if (userInput.equals("")) {                throw new CommandCancelException();            }        } while (pattern != null && !userInput.matches(pattern));        return userInput;    }    // 打印一组选项并返回用户选择的选项内容    private String prompt(String prompt, List<?> options) {        int index = promptIndex(prompt, options);        return options.get(index - 1).toString();    }    // 打印一组选项并返回用户选择的位置    private int promptIndex(String prompt, List<?> options) {        String menu = toMenu(prompt, options);        int index;        do {            index = Integer.parseInt(prompt(menu, NUMBERS_ONLY));        } while (index == 0 || index > options.size());        return index;    }    /**     * 生成菜单内容     *     * @param prompt  提示,在列出所有选项后打印出来     * @param options 选项     *     * @return 主菜单内容     */    private <T> String toMenu(String prompt, List<T> options) {        final ArrayList<String> lines = new ArrayList<>();        final AtomicInteger counter = new AtomicInteger();        options.forEach((t) -> {            int index = counter.incrementAndGet();            String line = index + ": " + t.toString();            lines.add(line);        });        return String.join("\n", lines) + "\n" + prompt + "(1-" + lines.size() + "):";    }    /**     * 执行用户命令     *     * @param command 用户命令序号     *     * @return 执行结果     */    private CommandResult executeCommand(String command) {        int index = Integer.parseInt(command);        if (index > 0 && index <= commands.size()) {            return commands.get(index - 1).execute();        } else {            return CommandResult.OK;        }    }    ////////////////////////////////////////////////////////////////    static enum CommandResult {        OK("命令已完成。"), FAIL("命令已取消。"), EXIT("");        public String prompt;   // 在每个命令结束时打印出来        CommandResult(String prompt) {            this.prompt = prompt;        }    }    static enum BookType {文学类, 科学类, 杂志}    // 表示用户取消命令的异常    static class CommandCancelException extends RuntimeException {    }    static class Book {        public static final int EXPIRE_BORROW_DAYS = 21;        public String name;        public String author;        public String type;        public String borrowedBy;        public String borrowDate;        Book(String name, String author, String type) {            this.name = name;            this.author = author;            this.type = type;        }        public boolean isBorrowed() {            return this.borrowedBy != null;        }        @Override        public String toString() {            return name + ",作者:" + author + "," + type +                    (isBorrowed() ? " -- 已被'" + borrowedBy + "'于" + borrowDate + "借出" : "");        }        public boolean isExpired() {            if (!isBorrowed()) {                return false;            }            // 从当前时间反推过期的借阅时间。如果实际借阅时间在过期的借阅时间之前,则表示过期了            LocalDate maxBorrowDate = LocalDate.now().minus(EXPIRE_BORROW_DAYS, ChronoUnit.DAYS);            String maxBorrowDateStr = DateTimeFormatter.ofPattern("yyyyMMdd").format(maxBorrowDate);            return this.borrowDate.compareTo(maxBorrowDateStr) < 0;        }    }    static class Student {        public static final int MAX_BORROW = 3;        public String name;        Student(String name) {            this.name = name;        }        @Override        public String toString() {            return name;        }    }    ////////////////////////////////////////////////////////////////    class Library {        private List<Book> books = new ArrayList<>();        private List<Student> students = new ArrayList<>();        /**         * 添加书籍         *         * @param bookName 书名         * @param author   作者         * @param type     类型         *         * @return 执行结果         */        public CommandResult addBook(String bookName, String author, String type) {            if (books.stream().anyMatch((b) -> b.name.equals(bookName))) {                System.out.println("添加失败:书名已存在");                return CommandResult.FAIL;            }            this.books.add(new Book(bookName, author, type));            return CommandResult.OK;        }        public List<Book> availableBooks() {            return this.books.stream().filter((b) -> !b.isBorrowed()).collect(Collectors.toList());        }        public List<Book> borrowedBooks() {            return this.books.stream().filter(Book::isBorrowed).collect(Collectors.toList());        }        public List<Book> expiredBooks() {            return this.books.stream().filter(Book::isExpired).collect(Collectors.toList());        }        /**         * 删除书籍         *         * @param index 序号         *         * @return 执行结果         */        public CommandResult deleteBook(int index) {            this.books.remove(index);            return CommandResult.OK;        }        public int countBorrowedBooks(String student) {            return (int) this.books.stream().filter((b) -> student.equals(b.borrowedBy)).count();        }    }    ////////////////////////////////////////////////////////////////    /**     * 表示命令的抽象类     */    static abstract class Command {        public String title;  // 命令标题,将显示在主菜单中        abstract CommandResult execute();        @Override        public String toString() {            return title;        }    }    // 列出满足要求的对象    class ListCommand<T> extends Command {        private Supplier<List<T>> supplier; // 查询满足要求的对象的方法        private String title;               // 输出标题        ListCommand(String title, Supplier<List<T>> supplier) {            this.title = title;            this.supplier = supplier;        }        @Override        CommandResult execute() {            System.out.println("\n" + title);            supplier.get().forEach(System.out::println);            return CommandResult.OK;        }    }    // 添加图书    class AddBookCommand extends Command {        @Override        CommandResult execute() {            return library.addBook(                    prompt("请输入书名:", ANY_CONTENT),                    prompt("请输入作者:", ANY_CONTENT),                    prompt("请选择书籍类型:", Arrays.asList(BookType.values()))            );        }    }    // 删除图书    class DeleteBookCommand extends Command {        @Override        CommandResult execute() {            if (library.books.isEmpty()) {                System.out.println("没有可删除的书籍。");                return CommandResult.FAIL;            }            int index = promptIndex("请选择书籍序号", library.books);            return library.deleteBook(index - 1);        }    }    // 借阅图书    class BorrowBookCommand extends Command {        @Override        CommandResult execute() {            List<Book> availableBooks = library.availableBooks();            if (availableBooks.isEmpty()) {                System.out.println("没有可借阅的图书。");                return CommandResult.FAIL;            }            int index = promptIndex("请选择要借阅的图书", availableBooks);            Book book = availableBooks.get(index - 1);            String student = prompt("请选择借阅者:", library.students);            if (library.countBorrowedBooks(student) >= Student.MAX_BORROW) {                System.out.println("该同学不能借阅更多图书了。");                return CommandResult.FAIL;            }            String bDate = prompt("请输入借阅日期(YYYYMMDD):", "^\\d{8}$");            book.borrowedBy = student;            book.borrowDate = bDate;            return CommandResult.OK;        }    }    // 归还图书    class ReturnBookCommand extends Command {        @Override        CommandResult execute() {            List<Book> borrowedBooks = library.borrowedBooks();            if (borrowedBooks.isEmpty()) {                System.out.println("没有图书需要归还。");                return CommandResult.FAIL;            }            int index = promptIndex("请选择已借阅的图书", borrowedBooks);            Book book = borrowedBooks.get(index - 1);            book.borrowedBy = null;            book.borrowDate = null;            System.out.println("图书已归还。");            return CommandResult.OK;        }    }    // 退出程序    class ExitCommand extends Command {        @Override        CommandResult execute() {            return CommandResult.EXIT;        }    }}

不要等待机会,而要创造机会。

Java 小例子:图书馆课程设计(Java 8 版)

相关文章:

你感兴趣的文章:

标签云: