整合 多型+資料結構(順序表)+類+封裝+介面+繼承的面向物件編程的一個實用案例之:圖書館管理
重要邏輯
-
找物件
- 書有名字、作者、型別、價格、是都被借閱的狀態,可以作為一類物件
- 用戶可以有姓名等,可以成為一個物件,在此處,用戶又可細化為兩類(管理員和普通用戶),他們都可以獨成一類
- 對圖書的增刪查改這些行為可以作為物件,作為一類
-
創建物件
- 書有了,整合這些資料的資料結構在此處選擇較為簡單的順序表作為手段,后續學完資料庫,可以將資料放在資料庫中,
- 為了面向物件編程,我們將行為各成一派,所有派別都實作一個介面(所有派的掌門人),這里既可以認為是實作介面,也可以理解成繼承關系,為后續動態系結做鋪墊,
- 針對用戶方面,我們希望的是:一個用戶選擇身份后,其背后的邏輯(比如對應身份的選單(用一個陣列實作))已經初始化完成,再讓用戶進行下一步選擇時,已經可以進入功能(方法)的使用了,
-
使用物件
前述物件的互動,完成邏輯表達,
第一步:我們可以先針對書,建立一個包,該包下建立書類和順序表,之前都是寫在一個包里,現在是寫在一個包下的兩個類中,這也是真正的習慣之一,(注意事項已經寫在代碼注釋行)💛
package book;
public class Book {
private String name;
private String author;
private String type;
private int price;
private boolean isBorrowed;
//構造方法
public Book(String name, String author, String type, int price) {
this.name = name;
this.author = author;
this.type = type;
this.price = price;
}//isBorrowed默認為false,false表未借出
//為了列印出各個書,對toString進行重寫
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", type='" + type + '\'' +
", price=" + price +
(isBorrowed==true?" 已被借出 ":" 未被借出 ")+
'}';
}
//對書的各個私有成員提供介面
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 int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public boolean isBorrowed() {
return isBorrowed;
}
public void setBorrowed(boolean borrowed) {
isBorrowed = borrowed;
}
}
對BookList來說
package book;
import java.util.Arrays;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lebronHArden
* Date: 2021-12-08
* Time: 9:01
*/
public class BookList {
private Book[] books=new Book[10];
private int usedSize;
public BookList() {
books[0]=new Book("三國演義","羅貫中","小說",17);
books[1]=new Book("水滸傳","施耐庵","小說",44);
books[2]=new Book("西游記","吳承恩","小說",35);
this.usedSize=3;//不寫這個,那后續列印陣列時,這個數字默認就是0,那啥也列印不出
}
//獲取“書順序表的書的數量”
public int getUsedSize() {
return usedSize;
}
//設定書的數量
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
//獲取到pos位置處的書Book
public Book getPos(int pos){
if(pos<0||pos>this.usedSize){//this是否合理
System.out.println("下標不合法");
return null;
}
return books[pos];
}
//給pos位置插入一本書
public boolean isFull(){
return this.usedSize==this.books.length;
}
public void setPos(int pos,Book book){
if(isFull()){
this.books= Arrays.copyOf(this.books,2*this.books.length);//擴容兩倍
}
if(pos<0||pos>this.usedSize){
System.out.println("下標不合法");
return;
}
for (int i = this.usedSize-1; i >=pos ; i++) {
this.books[i+1]=this.books[i];
}
this.books[pos]=book;
this.usedSize++;
}
}
第二步:針對用戶:??
目前用戶的抽象我們只能想到只要是用戶都用名字,那就先寫出來,繼承關系也打好,
第三步:針對我們的Main函式:其邏輯
-
先建立書的順序表
-
讓用戶登錄,這里很重要,邏輯是:讓用戶選擇好身份后,我們的編譯器已經生成對應其身份的選單了!并且呢,不管用戶選哪個身份,我們都用User去接受,使其發生向上轉型,為什么讓它向上轉型?因為要實作多型!哪里多型?我們可以用父類參考列印不同子類的選單!哦!所以這里User和其子類中都要寫menu(),并使其構成重寫,不過列印出來的選單只是給我們看的,其實在列印之前,也就是讓用戶選擇身份的時候,再說白了,就是通過子類實體化物件的時候,這個對應選單的陣列就已經建立好了,
-
讓用戶根據其身份選擇功能,也就是說我們給用戶一個menu,他們能看到一些功能,他們做出選擇后(其實就是回傳值),我們的編譯器就能拿到對應的方法進行下一步的執行,
針對Main:
import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lebronHArden
* Date: 2021-12-08
* Time: 9:33
*/
public class Main {
public static User login(){
Scanner scanner=new Scanner(System.in);
System.out.println("請輸入姓名:");
String name=scanner.nextLine();
System.out.println("========請選擇訪問身份:1:管理員 0:普通用戶========");
int choice=scanner.nextInt();
while(true){
if(choice==1){
return new AdminUser(name);
}else if(choice==0){
return new NormalUser(name);
}else{
System.out.println("輸入錯誤,請重新輸入:");
}
}
}
public static void main(String[] args) {
BookList bookList=new BookList();//建一個書的順序表
User user=login();//向上轉型
while(true){
int choice=user.menu();//多型式列印各自的選單
user.doWork(choice,bookList);
}
}
}
當然我們的main函式編到子類用戶實體化的時候要去對子類用戶和用戶做思考:
-
子類和父類都要menu(),并且多型式列印
-
子類用戶實體化的時候,要產生對應的選單(陣列),反正兩類子類用戶都有對應的陣列,那再在父類用戶User中添一個欄位(操作的那個參考),這個參考也將在子類構造方法中先于子類自身構造時先被初始化,到這用戶這塊基本都齊全了,先思考到這,然后代碼給你們看看:
User:
package user;
import book.BookList;
import operation.IOperation;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lebronHArden
* Date: 2021-12-08
* Time: 9:23
*/
public abstract class User {
protected String name;
protected IOperation[] iOperations;
public abstract int menu();
public void doWork(int choice, BookList bookList){
iOperations[choice].work(bookList);
}
}
AdminUser:
package user;
import operation.*;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lebronHArden
* Date: 2021-12-08
* Time: 9:23
*/
public class AdminUser extends User{
public AdminUser(String name){
this.name=name;
this.iOperations=new IOperation[]{
new ExitOperation(),
new FindOperation(),
new AddOperation(),
new DelOperation(),
new DisplayOperation()
};
}
public int menu(){
System.out.println("========管理員選單========");
System.out.println("Hello "+this.name+" 歡迎來到圖書小練習");
System.out.println("0:退出系統");
System.out.println("1:查找圖書");
System.out.println("2:新增圖書");
System.out.println("3:洗掉圖書");
System.out.println("4:列印圖書");
System.out.println("請輸入你的選擇:");
Scanner scanner=new Scanner(System.in);
int choice =scanner.nextInt();
return choice;
}
}
NormalUser:
package user;
import operation.*;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lebronHArden
* Date: 2021-12-08
* Time: 9:23
*/
public class NormalUser extends User{
public NormalUser(String name){
this.name=name;//這個是對從父類繼承過來的成員進行初始化
this.iOperations=new IOperation[]{//這里我的理解也都是向上轉型
new ExitOperation(),
new FindOperation(),
new BorrowOperation(),
new ReturnOperation()
};
}
public int menu(){
System.out.println("========普通用戶選單========");
System.out.println("Hello "+this.name+" 歡迎來到圖書小練習");
System.out.println("0:退出系統");
System.out.println("1:查找圖書");
System.out.println("2:借閱圖書");
System.out.println("3:歸還圖書");
System.out.println("請輸入你的選擇:");
Scanner scanner=new Scanner(System.in);
int choice =scanner.nextInt();
return choice;
}
}
第三步:Main函式已經完成了2/3了,🌮
這里還是想通過父類參考實作多型的呼叫方法,那就繼續在User和子類用戶里新添一個方法(要構成重寫):doWork()
這個方法,要能根據選擇拿到陣列的元素,這個陣列元素你們發現了沒有,每個元素都是介面,那之前說了所有的方法都實作了這個介面,就相當于繼承,
這里通過IO介面又一次實作多型!
上代碼:IOperation:
package operation;
import book.BookList;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lebronHArden
* Date: 2021-12-08
* Time: 9:31
*/
public interface IOperation {
void work(BookList bookList);
}
功能函式: 
如AddOperation:
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* Description:
* User: lebronHArden
* Date: 2021-12-08
* Time: 9:25
*/
public class AddOperation implements IOperation{
public void work(BookList bookList){
System.out.println("新增圖書");
Scanner scanner=new Scanner(System.in);
System.out.println("請輸入書名:");
String name=scanner.nextLine();//書名
System.out.println("請輸入作者:");
String author=scanner.nextLine();//作者
System.out.println("請輸入書的型別:");
String type=scanner.nextLine();//書類
System.out.println("請輸入書的價格:");
int price=scanner.nextInt();//價格
Book book=new Book(name,author,type,price);
int curSize=bookList.getUsedSize();
bookList.setPos(curSize,book);
bookList.setUsedSize(curSize+1);
System.out.println("填加圖書成功");
System.out.println("===========================");
}
}
其余的留給讀者去實作,下篇博客給大家揭曉本人的答案(當然不一定最好)?
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/377071.html
標籤:其他
上一篇:Python從Abaqus輸出資料庫讀取歷史輸出資料(Abaqus幫助檔案學習筆記)
下一篇:(Java)構造二叉樹OJ題(LeetCode105 根據前序與中序構造二叉樹,LeetCode106 根據后序與中序構造二叉樹)
