作者:学Java的冬瓜
博客主页:☀冬瓜的主页
专栏:【Java刷题】
学习目标:
前面学习了类和对象的相关知识、面向对象的三大特征:封装,继承和多态。今天本文的目的:
- 将这些知识运用到具体的实际问题中,来解决图书管理的问题
- 初步认识面向对象编程的思想和方法。
Main:
import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User; //必须有User调用,不然login返回值不能是User
import java.util.Scanner;
public class Main {
public static User login() {
System.out.println("请输入你的名字:>");
Scanner scanner = new Scanner(System.in);
String userName = scanner.nextLine();
System.out.println("请输入你的身份: 1、管理员 2、普通用户:>");
int choice = scanner.nextInt();
//确保输入1或者2
while (choice !=1 && choice!=2) {
System.out.println("输入错误,请重新输入!");
System.out.println("请输入你的身份: 1、管理员 2、普通用户:>");
choice = scanner.nextInt();
}
//1、返回new的对象
//2、new的时候初始化对象的name
//3、用User类型对象接收new的对象,发生向上转型
if(choice==1) {
return new AdminUser(userName);
} else { //choice==2
return new NormalUser(userName);
}
}
public static void test() {
//0、准备书架 ,初始化放三本书
BookList bookList = new BookList();
//1、登录
User user = login(); //用User类型对象接收AdminUser或NormalUser类型的对象,发生向上转型
while(true){
//2、打印菜单并返回选择
int choice = user.menu();//发生多态(还有动态绑定)
//3、调用整合操作方法,进行操作
user.doOperations(choice,bookList);
}
}
public static void main(String[] args) {
test();//用test函数测试
}
}
package user;
import book.BookList;
import operation.IOperation;
/**
* 父类
**/
public abstract class User {
//封装name
private String name;
//不用private,不然在子类中访问iOperations并初始化很麻烦
protected IOperation[] iOperations;//只是定义了接口数组但没有初始化,内存也未分配
//1、需要管理员和普通用户相对应的两个菜单,所以设置成继承,进而可以使用多态
//2、父类中的menu不需要任何操作,所以可以改为抽象类
public abstract int menu();
public void doOperations(int choice, BookList bookList) {
this.iOperations[choice].work(bookList);//先得到choice下标的操作对象,再调用work方法
}
//构造方法初始化name
public User(String name) {
this.name=name;
}
//获取name
public String getName() {
return name;
}
}
package user;
import operation.*;
import java.util.Scanner;
/**
* 管理员
*/
public class AdminUser extends User{
//login中返回new的对象时,name和iOperation都完成初始化
public AdminUser(String name) {
super(name);//调用父类构造方法完成初始化
this.iOperations = new IOperation[] {
new Exit(),
new Add(),
new Delete(),
new Find(),
new Modify(),
new Display(),
};
}
public int menu() {
System.out.println("*********************************");
System.out.println("hello "+this.getName()+" 欢迎来到图书小练习!");
System.out.println("*********************************");
System.out.println("1、增添图书 2、删除图书");
System.out.println("3、查找图书 4、修改图书");
System.out.println("5、显示图书 0、退出系统");
System.out.println("*********************************");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的选择:>");
int choice = scanner.nextInt();
while(choice <0 || choice>=6) {
System.out.println("输入错误,请重新选择!");
System.out.println("请输入你的选择:>");
choice = scanner.nextInt();
}
return choice;
}
}
package user;
import operation.*;
import java.util.Scanner;
/**
* 普通用户
*/
public class NormalUser extends User{
//在子类构造方法中调用父类构造方法完成父类name的初始化
public NormalUser(String name) {
super(name);
this.iOperations = new IOperation[] {
new Exit(),
new Find(),
new Borrow(),
new Return()
};
}
public int menu() {
System.out.println("*********************************");
System.out.println("hello "+this.getName()+" 欢迎来到图书小练习!");
System.out.println("*********************************");
System.out.println("1、查找图书 2、借阅图书");
System.out.println("3、归还图书 0、退出系统");
System.out.println("*********************************");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的选择:>");
int choice = scanner.nextInt();
while(choice <0 || choice>=4) {
System.out.println("输入错误,请重新选择!");
System.out.println("请输入你的选择:>");
choice = scanner.nextInt();
}
return choice;
}
}
package book;
public class Book {
private String name;
private String author;
private int price;
private String type; //图书类型
private boolean isBorrowed; //图书是否借出
//创建构造方法,在new时传入并初始化书的信息
public Book(String name, String author, int price, String type) {
this.name = name;
this.author = author;
this.price = price;
this.type = type;
}
//查找等各种操作都需要输入图书名字,所以需要getName访问book的name信息
public String getName() {
return name;
}
//借阅和归还都需要设置book中的boolean值
public void setBorrowed(boolean borrowed) {
isBorrowed = borrowed;
}
//打印时防止打印book对象的地址,重写object类的toString方法
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", type='" + type + '\'' +
", isBorrowed=" + ((isBorrowed == false) ? "未借出" : "已借出") +
'}';
}
}
package book;
/**
* 书架
*/
public class BookList {
//封装books和usedSize
private Book[] books = new Book[10];
private int usedSize;
//构造方法,new书架bookList的时候,books中默认放入三本书
public BookList() {
books[0] = new Book("水浒传","施耐庵",59,"小说");
books[1] = new Book("西游记","吴承恩",38,"小说");
books[2] = new Book("三国演义","罗贯中",89,"小说");
this.usedSize = 3; //书的有效个数初始值
};
//用Add调用setPosBook是尾插法,Modify调用是是修改该位置
public void setPosBooks(int pos, Book book) {
this.books[pos] = book;
}
public Book getPosBooks(int pos) {
return this.books[pos];
}
public int getUsedSize() {
return usedSize;
}
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
}
//可以在这里,在BookList类中写增删查改等方法,来实现对Book[]类型的books操作
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class Add 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("请输入图书价格:>");
int price= scanner.nextInt();
scanner.nextLine();//接收上一步留下的回车键
System.out.println("请输入图书类型:>");
String type = scanner.nextLine();
//创建一个Book类型的对象存储这本书
Book book = new Book(name,author,price,type);
//把书放进书架(这里相当于尾插)
int currentUserSize = bookList.getUsedSize();
bookList.setPosBooks(currentUserSize,book);
bookList.setUsedSize(currentUserSize+1);
System.out.println("增添成功!");
}
}
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class Delete implements IOperation{
//添加要完善的话,也可以用和Delete相同地方法
public void work(BookList bookList) {
System.out.println("==删除图书==");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入图书名字:>");
String name = scanner.nextLine();
int index=-1;
int currentUsedSize = bookList.getUsedSize();
for (int i = 0; i < currentUsedSize; i++) {
Book book = bookList.getPosBooks(i);
if(book.getName().equals(name)) {//字符串的比较,用equals
index=i;
break;
}
}
if(index==-1){
System.out.println("没有你要删除的书!");
} else {
int start=index+1;
while(start<currentUsedSize) {
Book book = bookList.getPosBooks(start);
bookList.setPosBooks(start-1,book);
start++;
}
bookList.setPosBooks(currentUsedSize-1,null);
bookList.setUsedSize(currentUsedSize-1);
System.out.println("删除成功!");
}
}
}
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class Find implements IOperation{
public void work(BookList bookList) {
System.out.println("==查找图书==");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入图书名字:>");
String name = scanner.nextLine();
int currentUsedSize = bookList.getUsedSize();
for (int i = 0; i < currentUsedSize; i++) {
Book book = bookList.getPosBooks(i);
if(book.getName().equals(name)) {//字符串的比较,用equals
System.out.println("找到了!");
System.out.println(book);
return;
}
}
System.out.println("没有你要查找的书!");
}
}
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class Modify implements IOperation{
public void work(BookList bookList) {
//只能改价格
System.out.println("==修改图书==");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入图书名字:>");
String name = scanner.nextLine();
int index=-1;
int currentUsedSize = bookList.getUsedSize();
for (int i = 0; i < currentUsedSize; i++) {
Book book = bookList.getPosBooks(i);
if(book.getName().equals(name)) {//字符串的比较,用equals
index=i;
break;
}
}
if(index==-1){
System.out.println("没有你要修改的书!");
}else{
System.out.println("请输入你要修改成的相关信息:>");
System.out.println("请输入图书名字:>");
String mName = scanner.nextLine();
System.out.println("请输入作者姓名:>");
String mAuthor = scanner.nextLine();
System.out.println("请输入图书价格:>");
int mPrice= scanner.nextInt();
scanner.nextLine();//接收上一步留下的回车键
System.out.println("请输入图书类型:>");
String mType = scanner.nextLine();
//创建一个Book类型的对象存储这本书
Book book = new Book(mName,mAuthor,mPrice,mType);
//把书放进书架(这里相当于尾插)
bookList.setPosBooks(index,book);
System.out.println("修改成功!");
}
}
}
package operation;
import book.BookList;
public class Display implements IOperation{
public void work(BookList bookList) {
System.out.println("==显示图书==");
int currentUserSize = bookList.getUsedSize();
for (int i = 0; i < currentUserSize; i++) {
System.out.println(bookList.getPosBooks(i));
}
}
}
package operation;
import book.BookList;
public class Exit implements IOperation{
public void work(BookList bookList) {
System.out.println("==退出系统==");
System.exit(-1);
}
}
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class Borrow implements IOperation{
public void work(BookList bookList) {
System.out.println("==借阅图书==");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入图书名字:>");
String name = scanner.nextLine();
int currentUsedSize = bookList.getUsedSize();
for (int i = 0; i < currentUsedSize; i++) {
Book book = bookList.getPosBooks(i);
if(book.getName().equals(name)) {//字符串的比较,用equals
bookList.getPosBooks(i).setBorrowed(true);
System.out.println("借阅成功!");
return;
}
}
System.out.println("没有你要借阅的书!");
}
}
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
public class Return implements IOperation{
public void work(BookList bookList) {
System.out.println("==归还图书==");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入图书名字:>");
String name = scanner.nextLine();
int currentUsedSize = bookList.getUsedSize();
for (int i = 0; i < currentUsedSize; i++) {
Book book = bookList.getPosBooks(i);
if(book.getName().equals(name)) {//字符串的比较,用equals
bookList.getPosBooks(i).setBorrowed(false);
System.out.println("归还成功!");
return;
}
}
System.out.println("没有你要归还的书!");
}
}
面向对象和面向过程不一样,面向过程只是一种解决问题的方法,面向对象是根据对象去解决问题。 所以,面向对象第一步是找出对象。
- 对象第一类:人(User)(还分管理员(AdminUser)和普通用户(NormalUser),User是它俩的父类)
- 对象第二类:书(Book),有了书还得有书架(BookList)。
- 对象第三类:增删查改等操作(也可以在BookList中创建方法实现增删查改)
面向对象要有整体的思维,整体的框架。不是先完成一个函数就去测试,而是应该先把框架架构出来比如:
- 图书管理User类被AdminUser和NormalUser继承,3个类。
- 有Book和BookList,5个类。
- 有Add,Delete,Find,Modify,Display,Borrow,Return,Exit,这八个类实现一个接口IOperation。共16个类,1个接口。
注意:当然,这些框架也是一步一步写才知道需要用到继承,用到接口,用到抽象类。
比如在上面代码中,
- login登录方法在main类中操作,因为它只需要返回AdminUser或NormalUser对象,不需要访问其它。
- 整合操作的方法doOperation在父类User中操作,从而能够访问iOpreations接口数组,进而访问Add等增删查改的work()方法
最后:希望各位大佬批评指正!