程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java小例子:圖書館課程設計

Java小例子:圖書館課程設計

編輯:關於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.        @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(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.    @Override
506.    public String toString() {
507.        return name;
508.    }
509.} 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved