文章目录
- 图书管理系统框架一览图
- 整体思想:
- Book包
- Book类
- BookList类
- User包
- 普通用户Customer类
- 管理员Librarian类
- 用户(user)类---父类
- 功能包-- Operation包
- 创建接口--IOperation接口
- 新增图书--AddOperation
- 删除图书--RemoveOperation
- 查找图书--FindOperation
- 显示图书--DisplayOperation
- 整理图书--ArrangeOperation
- 借阅图书--LentOperation
- 归还图书--ReturnOperation
- Mian类--实现登录,连接程序
- 总结
前言:博主在之前的文章中分别介绍了,包,封装,继承和多态,总感觉哪里好像没有学透,所以今天特意复习了一下,用一个图书管理系统,把之前学过的东西全部运用进去。
前期文章: [java篇]包,继承和组合]
[java篇]多态,抽象类和接口
图书管理系统框架一览图
整体思想:
我们在敲代码之前先构思一下,即然要实现图书系统,那么就要有书,而图书馆里又不只有一本书,所以我们要出创建一个书架,存放所有的书。
当我们说到用户了,用户分为图书管理员和普通用户,而这两个用户又隶属于一个父类user类,因为我们在调用功能的时候普通用户和管理员有着相同的功能。
功能:我们创建一个功能接口
,让每个具体功能都实现功能接口中的抽象方法
。
Main类:创建登录方法,通过个人选择。去选择普通用户菜单,还是管理员菜单,然后通过菜单返回要具体实现的功能,调用Operation包下的某个功能类
- 创建一个书类:里面的属性包括:
书名
,作者
,书的类型
,价格
,此书有没有被借出
- 创建一个书架:里面包含
所有的书
,还有一些具体方法
- 在User包下,创建两个类,分别是
customer类
,和Librarian类
,都继承
了user类
。分别在两个子类中实现各自的菜单。
Book包
Book类
在Book类中,实现封装书的属性
,依次为 书名
,作者
,书的特性
,价格
,此书是否被借出
。
package Book;
public class Book {
//创建书的属性
//包括 书名 作者 种类 价格 是否借出
private String name;
private String author;
private String type;
private int price;
private boolean isLent;
//实现书的构造方法
public Book(String name, String author, String type, int price) {
this.name = name;
this.author = author;
this.type = type;
this.price = price;
}
//实现setter 和 getter 方法 以便在其他类中调用书的属性
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 isLent() {
return isLent;
}
public void setLent(boolean lent) {
isLent = lent;
}
//重写toString()方法
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", type='" + type + '\'' +
", price=" + price +
","+((isLent == false) ? "未借出" :"已借出") +
'}';
}
}
BookList类
实现书架,在这里创建一个Book数组,存放全部的书
,和一些方法的实现
public class BookList {
//实现书架
//其实在整个图书管理系统中,都是对书架的操作
public Book []books = new Book[10];//先初始化书的书目为10本,其实我们在这里还可以实现扩容
private int useSize;
public BookList(){
this.books[0] = new Book("水浒传","施耐庵","小说",45);
this.books[1] = new Book("三国演义","罗贯中","小说",40);
this.books[2] = new Book("西游记","吴承恩","小说",39);
this.books[3] = new Book("红楼梦","曹雪芹","小说",50);
this.useSize = 4; //现在具体书被初始化的有4本
}
public int getUseSize() { //获得书的书目
return useSize;
}
public void setUseSize(int useSize) { //设置书的书目
this.useSize = useSize;
}
public Book getPos(int size){ //得到对应下标的某本书
return books[size];
}
public void setBook(Book book,int size){ //设置在某个下标有某本书
books[size] = book;
}
public Book getBook(int size){ //得到对应下标的某本书
return books[size];
}
}
User包
普通用户Customer类
在Customer类中,他继承了user类
,拥有了user类中的属性,先调用父类中的构造方法
,然后在菜单中打印出各个功能的编号。并且在子类中的构造方法中实现一个功能数组
,这个数组的每个元素为对应菜单中的功能的对象
。
最后返回选择后的功能下标
。
package User;
import Operation.*;
import java.util.Scanner;
public class Customer extends user {
//调用父类的构造方法
public Customer(String name){
super(name);
this.iOperations = new IOperation[]{
new ExitOperation(),
new IsLentOperation(),
new ReturnOperation(),
new FindOperation()
};
}
public int menu(){
System.out.println("hello" + this.name + "欢迎来到图书管理系统");
System.out.println("============= 普通用户菜单 ==============");
System.out.println("1.借阅图书");
System.out.println("2.归还图书");
System.out.println("3.查找图书");
System.out.println("0.退出系统");
Scanner scanner = new Scanner(System.in);
int choice = scanner.nextInt();
return choice;
}
}
管理员Librarian类
和普通用户一样,先调用父类中的构造方法
,作为子类拥有父类中的所有属性(除private修饰外
),在子类的构造方法中创建功能数组
,数组中的每个元素都是对应专属管理员执行的功能对象
。然后打印管理员菜单。最后返回功能选择
。
package User;
import Operation.*;
import java.util.Scanner;
public class Librarian extends user{
public Librarian(String name){
super(name);
this.iOperations = new IOperation[]{
new ExitOperation(),
new AddOperation(),
new RemoveOperation(),
new FindOperation(),
new DisplayOperation(),
new ArrangeOperation()
};
}
public int menu(){
System.out.println("hello" + this.name + "欢迎来到图书管理系统");
System.out.println("============= 管理员菜单 ==============");
System.out.println("1.新增图书");
System.out.println("2.删除图书");
System.out.println("3.查找图书");
System.out.println("4.显示图书");
System.out.println("5.整理图书");
System.out.println("0.退出系统");
Scanner scanner = new Scanner(System.in);
int choice = scanner.nextInt();
return choice;//返回功能下标
}
}
用户(user)类—父类
在父类user类,先封装一个属性,即用户的名字
,然后通过构造方法对这个属性进行初始化
,我们现在可以使用abstract来修饰父类
,在父类中的所有抽象方法,都要在子类中被重写,我们在父类中写一个抽象方法为void menu()方法,当调用我们选择的功能下标时,我们可以直接调用父类中的menu方法。实现向上转型,动态绑定
。
package User;
import Book.BookList;
import Operation.IOperation;
public abstract class user {
//因为用户包含有两类
protected String name;
public user(String name){
this.name = name;
}
//实现菜单
public abstract int menu();
protected IOperation []iOperations; //创建一个功能数组
public void doOperation(int choice,BookList bookList){ //操作功能数组,并且调用功能包中的类中的被重写的方法。
iOperations[choice].work(bookList);
}
}
功能包-- Operation包
创建接口–IOperation接口
创建一个接口,让其他类实现接口中的抽象方法
package Operation;
import Book.BookList;
public interface IOperation {
void work(BookList bookList);
}
新增图书–AddOperation
首先在原有的书籍中查找有没有你要添加的图书
,如果有
就提示你此书已经存在,你无需添加
。在查找有没有这本书的时候我们需要遍历原书架上的所有书籍
,所以我们要在BookList类中实现一个方法得到所有的书
。如果在原有的书籍中没有找到你要添加的这本书,那么接在原来书架的末尾
,添加上这本书(调用BookList类中的setBook()方法)
,最后把书的个数加一(调用BookList类中的getsueSize()方法
)。
package Operation;
import Book.Book;
import Book.BookList;
import java.util.Scanner;
public class AddOperation implements IOperation{
public void work(BookList bookList){
System.out.println("新增图书");
System.out.println("请输入书名");
Scanner scanner = new Scanner(System.in);
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);
//在原有的书籍中查找是否已经存在了要添加的这本书
//得到书的每下标
for(int i = 0;i < bookList.getUseSize();i++) {
Book book1 = bookList.getPos(i);
if (name.equals(book1.getName())){
System.out.println("此书已经存在,无需添加");
return;
}
}
bookList.setBook(book,bookList.getUseSize()); //把这本书添加到书架的末尾
bookList.setUseSize(bookList.getUseSize()+1); //书的书目加1
System.out.println("添加成功");
}
}
删除图书–RemoveOperation
首先输入你要删除的图书,看书架上有没有这本书,如果没有就提示书库中没有你要删除的书
,如果书架上有,那么就让要删除的这本书的后一本书去覆盖将要删除的这本书,即[i] = [i+1]
.最后在原有的书架上的图书个数减一
。
package Operation;
import Book.Book;
import Book.BookList;
import java.util.Scanner;
public class RemoveOperation implements IOperation{
public void work(BookList bookList){
System.out.println("删除图书");
System.out.println("请输入删除的书名");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int pos = -1;
for(int i = 0;i<bookList.getUseSize();i++){
Book book = bookList.getPos(i);
if(book.getName().equals(name)) {
pos = 1;
}
}
if(pos == 1){
//进行删除
for(int i = pos;i<bookList.getUseSize() - 1;i++){
Book book = bookList.getPos(i+1);
bookList.setBook(book,i);
}
bookList.setUseSize(bookList.getUseSize() - 1);
System.out.println("删除成功");
}else{
System.out.println("没有你要删除的图书");
}
}
}
查找图书–FindOperation
package Operation;
import Book.Book;
import Book.BookList;
import java.util.Scanner;
public class FindOperation implements IOperation{
public void work(BookList bookList){
System.out.println("查找图书");
System.out.println("请输入你要查找的书籍");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
for(int i = 0;i<bookList.getUseSize();i++){
Book book = bookList.getPos(i);
if(book.getName().equals(name)){
System.out.println("已经找到");
System.out.println(book);
return;
}
}
System.out.println("找不到");
}
}
显示图书–DisplayOperation
package Operation;
import Book.Book;
import Book.BookList;
public class DisplayOperation implements IOperation{
public void work(BookList bookList){
System.out.println("显示所有图书");
if(bookList.getUseSize() == 0){
System.out.println("书库无书");
return;
}
for(int i = 0;i<bookList.getUseSize();i++){
System.out.println(bookList.getBook(i));
}
}
}
整理图书–ArrangeOperation
在整理图书的时候,博主设计了你要按怎样的方式进行整理,是书名,作者,类型,还是价格。这让我们不由的想到了上一篇博主介绍的Comparator接口,分别实现各自的构造器。,然后通过Arrays.sort()方法,对所有的书籍进行排序。在这里我们一定要格外的关注Arrays.sort(),方法中要传两个参数,第一个是你要对什么进行排序,简单的说也就是一个数组,例如我们现在要传的第一个参数就要是一个书籍数组,把所有的书籍整成一个数组,然后传进去,第二个参数是你实现的比较器类的对象。
在这里一共要建4个比较器。我们可以将它们整成数组。
Comparator []comparators;
书名比较器:
class NameComparator implements Comparator<Book>{
public int compare(Book book1,Book book2){
return book1.getName().compareTo(book2.getName());
}
}
作者比较器:
class AuthorComparator implements Comparator<Book>{
public int compare(Book book1,Book book2){
return book1.getAuthor().compareTo(book2.getAuthor());
}
}
特性比较器:
class TypeComparator implements Comparator<Book>{
public int compare(Book book1,Book book2){
return book1.getType().compareTo(book2.getType());
}
}
价格比较器:
class PriceComparator implements Comparator<Book>{
public int compare(Book book1,Book book2){
return book1.getPrice() - book2.getPrice();
}
}
注意:在实现接口的时候。我们一定要注意Comparator<>里边的泛型,他表示的是你要比较的东西的类型。
然后我们继续实现操作接口,因为Arrays.sort()的第一个参数是一个关于书的数组,所以我们要建立一个newBook数组,存放所有的书籍,我们还应该注意,我们不能向Arrays.sort()里直接传BookList.books因为它传过去的还有为被初始化的书籍,所以我们要出进去的是已经被初始化好的。
public class ArrangeOperation implements IOperation{
public Book[] arrayBook(Book []books,int size){
//把书架上的所有书籍全部转移到另一个数组中
Book []books1 = new Book[size];
for(int i = 0;i<size;i++){
books1[i] = new Book(books[i].getName(),books[i].getAuthor(),books[i].getType(),books[i].getPrice());
}
return books1;
}
public void work(BookList bookList){
System.out.println("你要怎样整理?");
System.out.println("0-->按书名整理 1-->按作者名字整理 2-->按书的价格整理 3-->按书的类型整理");
Scanner scanner = new Scanner(System.in);
Comparator []comparators = new Comparator[]{ //把构造器整成一个数组
new NameComparator(),
new AuthorComparator(),
new PriceComparator(),
new TypeComparator()
};
int choice = scanner.nextInt();
Book []newBooks arrayBook(bookList.books,bookList.getUseSize());
Arrays.sort(newBooks,comparators[choice]);
for(int i = 0;i<bookList.getUseSize();i++){ //显示排序后的书
System.out.println(newBooks[i]);
}
System.out.println("排序成功");
}
}
借阅图书–LentOperation
package Operation;
import Book.Book;
import Book.BookList;
import java.util.Scanner;
public class IsLentOperation implements IOperation{
public void work(BookList bookList){
System.out.println("借出图书");
System.out.println("请输入书名");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
for(int i = 0;i<bookList.getUseSize();i++){
Book book = bookList.getPos(i);
if(book.getName().equals(name)){
book.setLent(true);
System.out.println("借阅成功");
return;
}
}
System.out.println("图书馆没有你要借的书,或者此书已被人借走");
}
}
归还图书–ReturnOperation
package Operation;
import Book.Book;
import Book.BookList;
import java.util.Scanner;
public class ReturnOperation implements IOperation{
public void work(BookList bookList){
System.out.println("归还图书");
System.out.println("请输入还书书名");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
for(int i = 0;i<bookList.getUseSize();i++){
Book book = bookList.getPos(i);
if(book.getName().equals(name)){
book.setLent(false);
return;
}
}
System.out.println("还书失败");
}
}
Mian类–实现登录,连接程序
在调用各个功能之前,我们首向要实现一个登陆页面。
首先让使用者,输入自己的姓名,然后选择管理员,还是普通用户,根据不同的选择调用不同的菜单。
//创建一个登陆页面
public static user login(){
System.out.println("请输入姓名");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("请选择 0--> 管理员 1--> 普通用户");
int choice = scanner.nextInt();
if(choice == 0){
return new Librarian(name);
}else{
//调用普通用户类
return new Customer(name);
}
}
然后连接代码全部,第一步实现登陆页面,第二步通过向上转型,动态绑定之后,返回选择之后的功能下标,然后根据功能下标,调用不同的功能方法来操作书架。
public static void main(String[] args) {
user user = login();
BookList bookList = new BookList();
while(true){
int choice = user.menu();
user.doOperation(choice,bookList);
}
}
总结
要实现一个普通的小项目,之前一定要有自己的结构框架,如何快速学习封装继承,和多态。老实人告诉你,多写代码,多练习!!!