目錄
目錄
前言
🔔1.library包
1.1 Book類
1.2 BookList類
🔔2.user包
2.1User類(父類)
2.2Admin(管理員)
2.3 NormalUser(普通用戶)
🔔3.Operation包
🕐3.1 IOperation接口
🕑3.2ListOperation(查看操作)
🕒3.3AddOperation(增加操作)
🕓3.4BorrowOperation(借書操作)
🕔3.5ReturnOperation(還書操作)
🕕3.6DelOperation(刪除操作)
🕖3.7FindOperation(查找操作)?
🕗3.8ExitOperation(退出操作)
🔔4.Main類
🔔5.效果展示
(ps:?在本篇文章中我們介紹了圖書管理系統📖,但是功能很少,所以在下一篇文章中,我又增加了幾個功能:大家可以點擊鏈接移步到下一篇文章(無講解的))
https://blog.csdn.net/2401_84024092/article/details/147874135?fromshare=blogdetail&sharetype=blogdetail&sharerId=147874135&sharerefer=PC&sharesource=2401_84024092&sharefrom=from_link
前言
🌈本篇文章會實現一個控制臺版本的“圖書管理系統”,涉及到 JavaSE中的繼承,多態,抽象類,接口。(代碼部分附有詳細的講解?)
在這個系統中:
1.能夠表示多本圖書的信息📘
2.提供兩種用戶:管理員和普通用戶
3.普通用戶可以查看書籍列表,查找圖書📖,借書,還書
4.管理員可以查看書籍列表,查找圖書📖,新增圖書,刪除圖書
整體框架如下:🎉
程序目錄如下:🎉
🔔1.library包
1.1 Book類
👉每本書📕都被定義為一個類,其中包含書名、作者、類型、價格和借閱狀態等屬性。這些屬性均被設置為private訪問權限,并通過getter和setter方法進行訪問和修改。在類的構造方法中,我們會對這些屬性進行初始化,其中借閱狀態默認設置為未借出(false)。
package library;
//一本書
public class Book {//現實世界的書private String name;private String author;private String type;private double price;private boolean isBorrowed;public Book(String name, String author, String type, double price){this.name=name;this.author=author;this.type=type;this.price=price;this.isBorrowed=false;}//alt+ins自動生成
//get,set方法可以隨時更改屬性,但是構造方法只能初始化一次public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String getType() {return type;}public void setType(String type) {this.type = type;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public boolean isBorrowed() {return isBorrowed;}public void setBorrowed(boolean borrowed) {isBorrowed = borrowed;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", type='" + type + '\'' +", price=" + price +", isBorrowed=" + (isBorrowed?"已借出":"未借出") +'}';}
}
1.2 BookList類
👉用來管理多個書籍對象
首先定義一個Book類類型的數組books,共分配1024個空間
?注意:我們約定好,所有有效的書籍,都是從0開始連續遞增排列的,以便可以通過size來描述有效書籍數目
package library;public class BookList {private Book[] books=new Book[1024];//此數組中每個類型都是Book類類型//長度不方便靈活調整,預先創造大空間//把booklist想象為一個書架,書架總共有1024個位置,不能修改大小,所以設置為private//長度不方便靈活調整,預先創造大空間private int size =0;//有效元素public BookList(){books[0]=new Book("西游記","吳承恩","古典小說",100);//books[0]中存放的是一組實例對象books[1]=new Book("紅樓夢","曹雪芹","古典小說",90);books[2]=new Book("高等數學","高斯","數學",40);books[3]=new Book("Java入門","詹姆斯高斯林","計算機",70);books[4]=new Book("紅樓夢","曹雪芹","古典小說",90);size=5;}public Book getBook(int index) {//得到序號為index的書籍return books[index];//不會越界,因為此時還沒滿}public void setBook(int index,Book book) {books[index] = book;}//將序號index處設置為××書public int getSize() {return size;//有效書籍數量}public void setSize(int size) {this.size = size;//設置有效書籍數量}
}
🔔2.user包
兩種用戶:普通用戶🙎?♀?+管理員👩?🏫
?注意:普通用戶與管理員的操作即存在重復的部分,也存在不同的部分,因此可以通過繼承,把相同的部分通過父類(User)提取出來
2.1User類(父類)
將抽象菜單方法(menu)定義在父類中,供子類重寫實現,并通過 IOperation[] 數組存儲管理員和用戶可執行的功能操作。
package library.user;import library.BookList;
import library.IOperation;public abstract class User {//不同 的用戶不同的操作protected String name;//各個子類都有的內容,直接放在父類中//protected子類可以直接獲取到,不必再去用getter setterprotected IOperation[] operations;//當前這個類能進行那些操作,就往這個數組里添加對應的對象public User(String name){this.name=name;}public abstract int menu();//不知道父類的菜單(父類就沒有菜單),我知道的只有管理員和用戶的菜單// 所以使用abstract,子類再進行重寫//為了避免父類被不小心創建出實例,所以要抽象(因為不能出現“父類菜單”)public void work(int choice, BookList bookList){//3.進入到父類的work方法if(choice<0||choice>=operations.length){System.out.println("輸入的選項非法");return;}operations[choice].work(bookList);//4.調用我選擇的方法里面的work方法,就能用此方法對booklist進行操作了}
}
2.2Admin(管理員)
🔔管理員應繼承父類User,通過重寫父類的 menu
方法,實現了自定義菜單功能,用戶可通過輸入選擇進入相應功能模塊。在子類構造函數中,首先調用父類構造方法完成名稱初始化,隨后對用戶操作進行配置(包括退出,查看,查找、新增、刪除的功能)。
注意:IOperation[]中的順序已經和菜單中的選項對應了
package library.user;import library.IOperation;
import library.Operation.*;import java.util.Scanner;public class Admin extends User{//private IOperation[] operations;//存放管理員的方法,這是什么類型呢,接口類型public Admin(String name) {super(name);operations=new IOperation[]{new ExitOperation(),new ListOperation(),new FindOperation(),new AddOperation(),new DelOperation(),};}@Overridepublic int menu() {System.out.println("==============================");System.out.println("歡迎您,"+name+"!");System.out.println("1.查看書籍列表");System.out.println("2.按照名字查找圖書");System.out.println("3.新增圖書");System.out.println("4.刪除圖書");System.out.println("0.退出");System.out.println("===============================");System.out.println("請輸入您的操作:");Scanner scanner=new Scanner(System.in);int choice = scanner.nextInt();return choice;}
}
2.3 NormalUser(普通用戶)
🔔普通用戶應繼承父類User,通過重寫父類的 menu
方法,實現了自定義菜單功能,用戶可通過輸入選擇進入相應功能模塊。在子類構造函數中,首先調用父類構造方法完成名稱初始化,隨后對用戶操作進行配置(包括退出,查看,查找、借書、還書的功能)。
package library.user;import library.Operation.IOperation;
import library.Operation.*;import java.util.Scanner;public class NormalUser extends User {//private IOperation[] operations;public NormalUser(String name) {super(name);//對所要的方法進行初始化operations = new IOperation[]{//普通用戶進行的操作new ExitOperation(),//這是一個數組,此處下標為0new ListOperation(),new FindOperation(),new BorrowOperation(),new ReturnOperation(),};}@Overridepublic int menu() {//打印菜單System.out.println("==============================");System.out.println("歡迎你,"+name+"!");//查看書籍列表//查找圖書System.out.println("1.查看書籍列表");System.out.println("2.按照名字查找圖書");System.out.println("3.借閱圖書");System.out.println("4.歸還圖書");System.out.println("0.退出");System.out.println("===============================");System.out.println("請輸入您的操作:");Scanner scanner=new Scanner(System.in);int choice = scanner.nextInt();return choice;}
}
🔔3.Operation包
👓此包中包括所有需要進行的操作類
🔔🔔🔔看到這里我們發現,書籍和用戶并沒有建立起聯系,那么如何將BookList與用戶實現“交互”呢??
通過IOperation接口把用戶和書給關聯起來
🕐3.1 IOperation接口
增加這個接口后,所有的操作類都要實現自IOperation接口,并重寫其中的work方法,在每個操作類中的work方法的具體實現各不相同。
?注意:這里有人可能會問:如果不設置接口,只在每個類中都寫上work方法,將參數BookList作為參數傳遞進去不就可以進行書籍與操作的聯系嗎,為什么還要設置接口呢?
原因:簡單來說就是限制代碼的靈活性
解釋:理論上是可行的,但是不加接口的話,無法保證所有的類都提供了work方法,也沒法保證work方法的參數都是相同的。而加上后就能強制統一,方便后續的調用,否則如果大家提供的方法各不相同,就會顯得很亂。
package library.Operation;import library.BookList;public interface IOperation {//也可以使用抽象類,但是我這個接口我只想保存一些方法,并沒有什么實例屬性要繼承的//并且不能多繼承//而User中的類是抽象性,因為我們需要繼承name的屬性void work(BookList bookList);
}
🕑3.2ListOperation(查看操作)
?在每一次循環中都會創建一次book對象
?接著調用booklist中的getBook方法獲取到第i本書
當i為0時,創建的對象就是
Book book = new Book("西游記","吳承恩","古典小說",100);
最后實現打印操作,當打印book時,會自動調用Book類中的toString方法(打印格式可以自行調整)
package library.Operation;import library.Book;
import library.BookList;public class ListOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("查看書籍列表");for(int i=0;i<bookList.getSize();i++){Book book = bookList.getBook(i);//拿到第i本書System.out.println("["+i+"]"+book);}}
}
🕒3.3AddOperation(增加操作)
?讓用戶輸入新的書籍📕的信息,然后把這個新的書放到BookList中
?這本新書存放到數組的最后一個位置上,在BookList中已經存在N本書了(size),這些書對應的下標[0,N-1],新的圖書📕就放到N的位置即可,在相應位置傳入書后,有效元素size也要加一。
package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class AddOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("新增圖書");Scanner scanner=new Scanner(System.in);System.out.println("請輸入書名:");String name = scanner.next();System.out.println("請輸入作者:");String author =scanner.next();System.out.println("請輸入價格");double price = scanner.nextDouble();System.out.println("請輸入類別");String type=scanner.next();Book book =new Book(name,author,type,price);int size=bookList.getSize();bookList.setBook(size,book);//傳入book就相當于傳入引用的空間bookList.setSize(size+1);//不能忘了修改sizeSystem.out.println("新增圖書完成!");}
}
🕓3.4BorrowOperation(借書操作)
?在借書操作時,要注意判斷是否被借出
package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class BorrowOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("借書");Scanner scanner=new Scanner(System.in);System.out.println("請輸入要借閱的圖書編號:");int id= scanner.nextInt();if(id<0||id>=bookList.getSize()){System.out.println("輸入錯誤");return;}Book book=bookList.getBook(id);//獲取第id本書對象if(book.isBorrowed()){//先判斷一下是否被借出System.out.println("該書已經被借出了");//如果真就被借出了return;}book.setBorrowed(true);//沒借出我就可以借了System.out.println("借書成功!");}
}
🕔3.5ReturnOperation(還書操作)
?在借書操作時,也要注意判斷書是否已經被歸還了
package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class ReturnOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("還書");Scanner scanner=new Scanner(System.in);System.out.println("請輸入要歸還的圖書編號:");int id= scanner.nextInt();if(id<0||id>=bookList.getSize()){System.out.println("輸入錯誤");return;}Book book=bookList.getBook(id);if(!book.isBorrowed()){//先判斷一下是否被借出falseSystem.out.println("該書沒借出,不能歸還");//如果沒被借出了,就不能換return;}book.setBorrowed(false);System.out.println("還書成功!");}
}
🕕3.6DelOperation(刪除操作)
?在進行刪除操作時,如果是最后一本書📕,直接將有效元素size-1即可
如果是中間位置元素,可以把最后一本書📕放在待刪除元素的位置上,然后再size-1即可。
package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class DelOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("刪除書籍");Scanner scanner=new Scanner(System.in);System.out.println("請輸入要刪除書籍的序號:");int index=scanner.nextInt();if(index<0||index>=bookList.getSize()) {System.out.println("序號超出范圍");return;}if(index == bookList.getSize()-1){bookList.setSize(bookList.getSize()-1);//如果是最后一本書,直接將有效元素設置為size-1即可}else{//如果刪除中間元素,就可以把最后一個元素,復制到待刪除元素的位置上,然后size-1即可Book lastBook = bookList.getBook(bookList.getSize()-1);//先獲取到最后一本書bookList.setBook(index,lastBook);bookList.setSize(bookList.getSize()-1);}System.out.println("刪除書籍完成!");}
}
🕖3.7FindOperation(查找操作)?
?查找操作只需驗證輸入內容與書籍列表中的條目是否一致。
package library.Operation;import library.Book;
import library.BookList;import java.util.Scanner;public class FindOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("查找操作");Scanner scanner=new Scanner(System.in);System.out.println("請輸入查找的書名");String name =scanner.next();for(int i=0;i<bookList.getSize();i++){Book book = bookList.getBook(i);if(book.getName().equals(name)){//比較字符串用這個System.out.println(book);}}System.out.println("查找完畢");}
}
🕗3.8ExitOperation(退出操作)
package library.Operation;import library.BookList;public class ExitOperation implements IOperation {@Overridepublic void work(BookList bookList) {System.out.println("goodbye!");System.exit(0);//退出整個程序}
}
🔔4.Main類
?在主類中根據用戶輸入跳轉到具體的用戶
package library;import library.user.NormalUser;
import library.user.User;
import library.user.Admin;
import java.util.Scanner;
public class Main {private static User login(){System.out.println("請輸入您的姓名:");Scanner scanner =new Scanner(System.in);String name = scanner.next();System.out.println("請輸入您的角色(1.普通用戶2.管理員)");int role = scanner.nextInt();if (role==1){return new NormalUser(name);}else if(role==2){return new Admin(name);}else{System.out.println("輸入的角色有誤");return null;}}public static void main(String[] args) {//書記管理library.BookList booklist=new BookList();//管理員和普通用戶讓用戶選擇User user = login();//User user=new NormalUser(name)//User user=new Admin(name)//向上轉型while(true){int choice = user.menu();//多態user.work(choice,booklist);//將選擇的菜單與書籍列表傳入,假如是查找,普通用戶}}
}