Java是一门面向对象的编程语言,要写一个图书管理系统,那么我们要做的就是去“找对象,创对象,使用对象”。
对于一个图书管理系统,里面的图书肯定就是一个对象,我们借书还书的时候都需要对图书进行操作,那么还需要一个图书类型的一个数组,也就是一个书架,而对于用户来说,又分为管理员和普通用户,它们的界面和对于图书的操作都是不一样的,也是两个对象。
对象找完,下面就开始写代码了
- 首先创建一个图书的类
public class Book {//书的类,通过这个类可以产生很多书
private String name;
private int price;
private String author;
private String type;
private boolean isBorrowed;
public Book(String name, int price, String author, String type) {
this.name = name;
this.price = price;
this.author = author;
this.type = type;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
public String getAuthor() {
return author;
}
public String getType() {
return type;
}
public boolean isBorrowed() {
return isBorrowed;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(int price) {
this.price = price;
}
public void setAuthor(String author) {
this.author = author;
}
public void setType(String type) {
this.type = type;
}
public void setBorrowed(boolean borrowed) {
isBorrowed = borrowed;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
", author='" + author + '\'' +
", type='" + type + '\'' +
", isBorrowed=" + isBorrowed +
'}';
}
}
注:重写object父类的toString方法可以直接打印Book中的属性,不用再写一些方法来打印
- 然后创建一个图书类型的顺序表
public class BookList {//相当于顺序表,相当于一个书架
public Book[] books = new Book[100];//一个Book类型的数组,里面最多放100本书,相当于里面最多放100个Book类型的对象
private int usedSize = 0;
public BookList() {
books[0] = new Book("三国演义",55,"罗贯中","小说");//此时相当于在0号下标放一个Book对象
books[1] = new Book("Java编程思想",60,"张松松","编程");
books[2] = new Book("西游记",52,"吴承恩","小说");//只要new,就会产生对应的对象,然后通过构造方法赋值
this.usedSize = 3;
}
//我们可以把对图书的所有操作都写到这个类中,比如删除,增加,借阅,归还,因为这个相当于就是一个顺序表,只不过里面存储的是一个自定义类型
//但是这里也可以单独写到一个包里面,写成一个接口的形式
public void setBooks(int pos,Book book) {//在pos位置放入一本Book类型的书
this.books[pos] = book;
}
public Book getBooks(int pos) {
return this.books[pos];
}
public int getUsedSize() {
return usedSize;
}
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
}
注:可以将对图书的操作直接写到这个顺序表里面,因为这些操作相当于就是在给顺序表进行增删改查。为了熟练一下接口的使用,我把它们都单独的写到类中
- 可以写一个User类作为管理员和普通用户的父类,因为它们都具有名字和选择按钮这两个属性和方法。
public abstract class User {//对于用户来说,分为管理员和普通用户,而它们都有一个共同的特性就是名字,那么就可以直接让它们继承这个类,就不用再写多余的代码
protected String name;
protected Ioperation[] operations;//定义一个Ioperation类型的数组,Admin和nor和这个类是继承关系,所以此时它们中也有这个数组
public User(String name) {
this.name = name;
}
public abstract int menu();
public void doOperation(BookList booklist, int chice) {//把选择的chice传过来,work方法中又有一个booklist参数
//这个方法也会继承给对应的子类,当进入对应的菜单界面,就会根据chice来调用对应的work操作
this.operations[chice].work(booklist);//相当于调用这个数组中的chice下标的对象中的work方法
}
}
- 创建一个管理员的类
public class Admin extends User { //这个就是管理员的类
public Admin(String name) {
super(name);
this.operations = new Ioperation[]{
new ExitOperition(),
new AddOperation(),
new FindOperation(),
new BelOperation(),
new DisplayOperation()
};
}
@Override
public int menu() {//这是管理员菜单的打印
System.out.println("=========================");
System.out.println("Hello"+name+",欢迎来到图书管理系统");
System.out.println("1.新增图书");
System.out.println("2.查找图书");
System.out.println("3.删除图书");
System.out.println("4.显示所有图书");
System.out.println("0.退出系统");
System.out.println("=========================");
Scanner scan = new Scanner(System.in);
int chice = scan.nextInt();//输入的是几就直接返回,然后调用对应的操作方法
return chice;
}
}
- 创建一个普通用户的类
public class Nor extends User{ //这个就相当于普通用户的类,因为它和管理员都具有相同的属性,所以可以直接继承User这个类
public Nor(String name) {
super(name);//相当于先帮助父类完成构造方法,
this.operations = new Ioperation[]{
new ExitOperition(),//因为这是数组,0号下标对应的是第一个操作,加入我输入了一个0,那么此时就应该是退出系统的操作
new FindOperation(),
new BorrowOperition(),
new ReturnOperation()
};
}
@Override
public int menu() {
System.out.println("=========================");
System.out.println("Hello"+name+",欢迎来到图书管理系统");
System.out.println("1.查找图书");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("0.退出系统");
System.out.println("=========================");
Scanner scan = new Scanner(System.in);
int chice = scan.nextInt();
return chice;
}
}
- 对顺序表的操作的类
首先这些类都实现了一个接口,便于直接通过这个接口的引用来调用这些操作
public interface Ioperation {
void work(BookList book);
}
①新增图书:
public class AddOperation implements Ioperation {
@Override
public void work(BookList books) {//是对books这个数组的操作,默认是以尾插法的形式进行插入
System.out.println("新增图书");
Scanner scan = new Scanner(System.in);
System.out.println("请输入图书的名字");
String name = scan.nextLine();
System.out.println("请输入图书的作者");
String author = scan.nextLine();
System.out.println("请输入图书的价格");
int price = scan.nextInt();
System.out.println("请输入图书的类型");
String type = scan.next();
Book book = new Book(name,price,author,type);//此时就将这几个组装成了一本书
int cursize = books.getUsedSize();//把usedsize赋值给cursize,来作为放入的标准,此时为3,因为是数组,也就是放在第四个位置
//books.setBooks(cursize,book);
books.books[cursize] = book;
books.setUsedSize(cursize+1);//当数组没被封装的时候,可以不用公共方法,直接通过引用访问数组
System.out.println("新增成功");
}
}
②删除图书:
public class BelOperation implements Ioperation{
@Override
public void work(BookList book) {
System.out.println("删除图书");
System.out.println("请输入要删除图书的名字");
Scanner scan = new Scanner(System.in);
String name = scan.nextLine();
int i = 0;
for( i = 0;i<book.getUsedSize();i++) {
Book bookss = book.getBooks(i);
if(bookss.getName().equals(name)){
break;
}
}
if(i==book.getUsedSize()) {
System.out.println("没有要删除的书籍");//说明此时是因为遍历完数组也没有找到要删除的书而退出的循环
return;
}
for(int pos = i;pos<book.getUsedSize()-1;pos++) {
Book bookss = book.getBooks(pos+1);
book.setBooks(pos,bookss);
}
book.setUsedSize(book.getUsedSize()-1);
System.out.println("删除成功");
}
}
③显示所有图书:
public class DisplayOperation implements Ioperation{
@Override
public void work(BookList book) {
System.out.println("显示所有图书");
for(int i = 0;i<book.getUsedSize();i++) {
Book bookss = book.getBooks(i);//通过Book类型的引用来接收getBooks传过来的数组中i号下标的book对象
System.out.println(bookss);//这里就是通过toString方法打印图书
}
}
}
④查找图书:
public class FindOperation implements Ioperation{
@Override
public void work(BookList book) {
System.out.println("查找图书");
System.out.println("请输入你要查找的图书");
Scanner scan = new Scanner(System.in);
String name = scan.nextLine();
for(int i = 0;i<book.getUsedSize();i++) {
Book bookss = book.getBooks(i);
if (bookss.getName().equals(name)) {
System.out.println(bookss);
System.out.println("找到此书籍");
return;
}
}
System.out.println("这本书已经被借出");
}
}
⑤借阅图书:
public class BorrowOperition implements Ioperation{
@Override
public void work(BookList book) {
System.out.println("借阅图书");
Scanner scan = new Scanner(System.in);
System.out.println("请输入图书的名字");
String name = scan.nextLine();
for(int i = 0;i<book.getUsedSize();i++) {//首先遍历数组判断那本书是否在
Book bookss = book.getBooks(i);//每拿到一本书就判断一下它的名字和这里输入的名字一不一样
if(bookss.getName().equals(name)){
bookss.setBorrowed(true);
System.out.println("借阅成功");
return;
}
}
System.out.println("已经被借出");//此时说明遍历数组没有发现和输入的名字一样的书
}
}
⑥归还图书:
public class ReturnOperation implements Ioperation{
@Override
public void work(BookList book) {
System.out.println("归还图书");
System.out.println("请输入要归还的图书名字");
Scanner scan = new Scanner(System.in);
String name = scan.nextLine();
for(int i = 0;i<book.getUsedSize();i++) {
Book bookss = book.getBooks(i);
if(bookss.getName().equals(name)){
bookss.setBorrowed(false);
System.out.println("归还成功");
return;
}
}
System.out.println("没有你要归还的图书");
}
}
⑦退出系统:
public class ExitOperition implements Ioperation{
@Override
public void work(BookList book) {
System.out.println("退出系统");
System.exit(0);//这个代表安全退出系统
}
}
- 最后是主函数。在主函数中将类实例化。
public class TestMain {//主函数
public static User login() {
Scanner scan = new Scanner(System.in);
System.out.println("请输入姓名"+" ");
String name = scan.nextLine();//此时的姓名就从键盘输入进去了
System.out.println("请输入你的身份:1--》管理员,2--》普通用户");
int chice = scan.nextInt();//此时如果输的是1,就是管理员,此时就来到管理员得菜单界面,如果是2,就是普通用户
if(chice==1) {
Admin admin = new Admin(name);//如果输入的是1,此时就创建一个管理员对象,然后返回,此时就发生了向上转型,
return admin;
}else{//此时代表普通用户
Nor nor = new Nor(name);
return nor;
}//为什么返回不同的对象:因为对象不一样,所打印的菜单就不一样
}
public static void main(String[]args) {
//此时所有的类都写好了,第一步就是准备书籍
BookList booklist = new BookList();//此时就创建出了一个书架,里面默认有了三本书
//第二步,登录
User user = login();//此时login这个方法里面的返回值就是普通人和管理员这两个对象,然后让父类的引用来接受
//如果不写成向上转型得话,需要一个对象得引用访问一个对象的方法,使代码变得很杂乱,有太多的if else
while(true){
int chice = user.menu();//此时发生了动态绑定,可以通过父类引用调用到子类对象里面的重写方法了。
//此时就可以看到菜单了,然后输入对应的数字,就可以根据chice知道选择的是几了,然后就知道调用哪个对应的类中的方法
//此处问题:知道了选择的是几如何调用对应的操作:高博逻辑:
user.doOperation(booklist,chice);
}
}
}