目录
前言:
项目要求:
知识储备:
代码实现:
Main:
Books包:
Book:
BookList:
Operate包:
Operate:
addOperate:
deleteOperate:
exitOperate:
findOperate:
showOperate:
Persion包:
User:
Admin:
Reader:
前言:
随着javaSE的学习深入,我们已经明白了什么是类和对象,学会了继承和多态,抽象类和接口,那么我们就可以利用以上几个知识点来完成一个小项目图书管理系统来检验一下我们学习的成果,我们主要完成其框架和一些基本点(起到复习作用,不是为了业务)。
项目要求:
实现一个图书管理系统,有两个用户,普通用户和管理员,两个用户的业务不一样,实现其业务,书有书名,作者,价格,书的类型,是否被借出。
普通用户:0.退出系统 1.查找图书 2.借阅图书 3.归还图书
管理员用户:0.推出系统 1.查找图书 2.新增图书 3.删除图书 4.显示图书
知识储备:
java基本语法,类和对象,继承和多态,抽象类和接口。
具体效果如下动图所示。
代码实现:
为了培养优良的代码风格,我们将各个模块区分开来,故我们需要创建3个包(有关包如果不太了解的话可以看看封装和包)分别是Books和Operate,Person,功能和其的英文名一样,最后用一个Main类把他们串在一起。
Main:
动态绑定:也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体 调用那个类的方法.
先创建一个书架BookList(具体代码后续给出,重要的是思路),User是Admin(管理员)和Reader(普通用户)的父类,使用User来接受这是因为在代码编译的时候程序并不知道是普通用户还是管理员,只有在我们输入后才确定下来(动态绑定),发生向上转型。用一个while来实现循环输入,因为两个用户的菜单不一样,故我们可以在User中定义一个抽象方法,在两个具体子类中实现,放回的k即为我们的选择操作。user.doOperate(books,k)是我觉的这个项目最精彩的地方,这里先简单理解为调用user,对books进行第k个操作,具体我会在Operate部分详细解释。
import Person.*;
import java.util.Scanner;
import Books.*;public class Main {private static User Logon(){Scanner scanner = new Scanner(System.in);System.out.print("请输入你的姓名: ");String name = scanner.next();System.out.print("请输入你的身份: 1: 管理员 2: 普通用户-> : ");int index = scanner.nextInt();if(index == 1){return new Admin(name);}else if(index == 2){return new Reader(name);}else{System.out.println("输入错误");System.exit(0);return null;}}public static void main(String[] args) {BookList books = new BookList();User user = Logon();//动态绑定while(true){int k = user.menu();user.doOperate(books,k);}}
}
Books包:
在Books包中存储这两个类Book类中存储书的一般属性,BookList就是书架。
Book:
为了更加安全和代码的封装性我们把变量用private修饰,在下面用set和get方法来进行修改。构造方法不用构造isBorrowed因为没有初始化的话java默认为false。
package Books;/*** 书的基本参数*/
public class Book {private String name;private String author;private int price;private String type;//书的类型private boolean isBorrowed;//是否被借出 默认值是falsepublic Book(String name, String author, int price, String type) {this.name = name;this.author = author;this.price = price;this.type = type;}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 int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getType() {return type;}public void setType(String type) {this.type = type;}public boolean isBorrowed() {return isBorrowed;}public void setBorrowed(boolean borrowed) {isBorrowed = borrowed;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", author='" + author + '\'' +", price=" + price +", type='" + type + '\'' +", isBorrowed=" + ((isBorrowed == false) ? "未借出" : "已借阅") +//不确定加括号'}';}
}
要想使用println来直接打印Book的话必须要重写toString方法,下图是println的源码,在valueof中有obj.toStirng的参数,我们基本类型的toString系统已经实现,Book为我们自己定义的一个类所以要自己实现一下。
BookList:
书架上不仅要能放书还要能记录书本的个数,一开始直接初始化3本书方便我们后续调试。
package Books;/*** 书架*/
public class BookList {private Book[] books;//能放书private int BookSize;//记录书本的个数public BookList() {books = new Book[10];this.books[0] = new Book("三国演义","罗贯中",10,"小说");this.books[1] = new Book("西游记","吴承恩",9,"小说");this.books[2] = new Book("红楼梦","曹雪芹",19,"小说");this.BookSize = 3;}public Book[] getBooks() {return books;}public void setBooks(int index,Book books) {this.books[index] = books;}public int getBookSize() {return BookSize;}public void setBookSize(int bookSize) {BookSize = bookSize;}
}
Operate包:
Operate:
这里不是包是一个接口,因为每个操作都只要实现work功能故我们定义一个接口来规范我们的代码,方便后面进行向上转型,work前面可以不用加public abstract系统默认会给你加上。
package Operate;
import Books.*;public interface Operate {void work(BookList books);
}
addOperate:
由于本项目难点并不在业务的实现,主要集中在一个框架,故下面的借阅图书和归还图书就由读者自行实现(很简单的)。
package Operate;
import Books.*;
import java.util.*;public class addOperate implements Operate {@Overridepublic void work(BookList books) {Scanner scanner = new Scanner(System.in);System.out.println("请输入书名: ");String name = scanner.next();System.out.println("请输入作者: ");String author = scanner.next();System.out.println("请输入价格: ");int price = scanner.nextInt();System.out.println("请输入书的类型: ");String type = scanner.next();Book book = new Book(name,author,price,type);int usedSize = books.getBookSize();books.setBooks(usedSize,book);books.setBookSize(usedSize + 1);System.out.println("添加成功");System.out.println();}
}
deleteOperate:
package Operate;
import Books.*;
import java.util.Scanner;
public class deleteOperate implements Operate {public void work(BookList books){Scanner scanner = new Scanner(System.in);System.out.print("请输入你要删除书的书名: ");String name = scanner.next();Book[] book = books.getBooks();//浅拷贝int bookSize = books.getBookSize();for(int i = 0;i < bookSize;i++){if(name.equals(book[i].getName())){for(int j = i;j < bookSize - 1;j++){book[j] = book[j + 1];}book[bookSize - 1] = null;System.out.println("删除成功");System.out.println();books.setBookSize(bookSize - 1);return;}}System.out.println("该图书不存在,删除失败");System.out.println();}
}
exitOperate:
package Operate;
import Books.BookList;
public class exitOperate implements Operate{@Overridepublic void work(BookList books) {System.out.println("退出系统");System.exit(0);}
}
findOperate:
package Operate;
import Books.BookList;
import Books.Book;
import java.util.Scanner;
public class findOperate implements Operate {@Overridepublic void work(BookList books) {Scanner scanner = new Scanner(System.in);System.out.print("请输入你要查找书的名字: ");String name = scanner.next();Book[] book = books.getBooks();int usedSize = books.getBookSize();for(int i = 0;i < usedSize;i++){if(name.equals(book[i].getName())){System.out.println("找到了,信息如下: ");System.out.println(book[i]);System.out.println();return;}}System.out.println("该图书不存在");System.out.println();}
}
showOperate:
package Operate;
import Books.BookList;
import Books.Book;
public class showOperate implements Operate{@Overridepublic void work(BookList books) {int usedSize = books.getBookSize();Book[] book = books.getBooks();for(int i = 0;i < usedSize;i++){System.out.println(book[i]);}System.out.println();}
}
Persion包:
User是Admin和Reader的父类。
User:
用一个Operate[]的数组来存储我们上面实现的方法类,因为两个用户对于的方法是不一样的故使用Operate放在User中那个用户需要哪个方法直接new一个方法类在该数组中(向上转型),要调用的时候通过下标访问即可。因为菜单要根据具体是那个用户来具体实现故要把它抽象就可以不用实现,故我们要把User定义成抽象类。
package Person;
import Operate.*;
import Books.*;
public abstract class User {protected String name;protected Operate[] operates;public void doOperate(BookList books,int choice){operates[choice].work(books);}public User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public abstract int menu();//菜单
}
Admin:
利用super来调用父类的构造方法,在operates中需要什么方法类就直接new上那个方法类,需要注意的是下标的映射关系。继承一个抽象类其子类必须要重写抽象方法。
package Person;
import Operate.*;
import java.util.Scanner;
public class Admin extends User{public Admin(String name){super(name);this.operates = new Operate[]{new exitOperate(),new findOperate(),new addOperate(),new deleteOperate(),new showOperate()};}@Overridepublic int menu() {Scanner scanner = new Scanner(System.in);System.out.println("***********管理员***********");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.print("请输入你的操作: ");int index = scanner.nextInt();return index;}
}
Reader:
和上面的Admin一样这里就不再赘述。
package Person;
import java.util.Scanner;
import Operate.*;
public class Reader extends User{public Reader(String name){super(name);this.operates = new Operate[]{new exitOperate(),new findOperate(),new borrowOperate(),new returnOperate()};}@Overridepublic int menu() {Scanner scanner = new Scanner(System.in);System.out.println("***********读者***********");System.out.println("1.查找图书");System.out.println("2.借阅图书");System.out.println("3.归还图书");System.out.println("0.推出系统");System.out.println("**************************");System.out.print("请输入你的操作: ");int index = scanner.nextInt();return index;}
}
总结:大家最好自己实现一遍,实现的时候最好要明白自己在做什么,可以看看最后的结果来捋捋思路,可以看到我们使用到了接口,抽象类,包和继承的相关知识,只有在你使用他们的时候才会明白那里缺了。
结语:
其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。