整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理
Posted 一枚小比特
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理相关的知识,希望对你有一定的参考价值。
整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理
重要逻辑
-
找对象
- 书有名字、作者、类型、价格、是都被借阅的状态。可以作为一类对象
- 用户可以有姓名等,可以成为一个对象,在此处,用户又可细化为两类(管理员和普通用户),他们都可以独成一类
- 对图书的增删查改这些行为可以作为对象,作为一类
-
创建对象
- 书有了,整合这些数据的数据结构在此处选择较为简单的顺序表作为手段。后续学完数据库,可以将数据放在数据库中。
- 为了面向对象编程,我们将行为各成一派,所有派别都实现一个接口(所有派的掌门人),这里既可以认为是实现接口,也可以理解成继承关系,为后续动态绑定做铺垫。
- 针对用户方面,我们希望的是:一个用户选择身份后,其背后的逻辑(比如对应身份的菜单(用一个数组实现))已经初始化完成,再让用户进行下一步选择时,已经可以进入功能(方法)的使用了。
-
使用对象
前述对象的交互,完成逻辑表达。
第一步:我们可以先针对书,建立一个包,该包下建立书类和顺序表,之前都是写在一个包里,现在是写在一个包下的两个类中,这也是真正的习惯之一。(注意事项已经写在代码注释行)💛
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("===========================");
其余的留给读者去实现。下篇博客给大家揭晓本人的答案(当然不一定最好)⏰
以上是关于整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理的主要内容,如果未能解决你的问题,请参考以下文章