前言
在学习完SE基础语法之后,我们已经具备实现一些简单代码的能力了,同时为了整合我们前面学习过程中的知识点,加强我们对各个知识点的认知,我们可以利用SE基础语法中的知识点实现一个简单的图书管理系统。
1. 设计与分析
任何业务代码的实现过程都是基于对实际事物的认知,最后抽象成一个一个对应的类来实现。要实现一个图书管理系统,我们需要图书,用户以及对图书进行的操作;也就是说我们希望一个图书管理系统中拥有我们的用户,能够被借阅的图书信息,以及能够对借阅信息或其他针对图书操作进行管理组织的方法类。
1.1 相关类的设计
在对图书管理系统进行简单的分析后,我们能够抽象出一些简单的类:
//图书类: 组织每一本图书个体的相关信息
//书架类: 用来组织图书间的关系,例如:存放图书数量,书架中已拥有的图书信息
//用户类: 针对不同用户呈现的不同权限界面,如管理员和普通用户的不同界面
//操作类: 针对不同管理权限用户开放的不同针对图书的操作
//测试图书管理系统的测试类: 用来专门进行图书管理系统各个相应操作能否正确运行的测试类
经过上面的描述我们希望能够根据不同用户实现不同对图书的操作权限的图书管理系统,如下
-
对于管理员,我们希望能够拥有如下操作:
-
对于普通用户,我们希望能够对图书进行以下操作:
我们能够想象我们对象与对象的交互是基于不同权限用户对图书赋予的不同操作权限行为而产生的,也就是说不同对象对同一行为进行操作而产生的不同结果,这也就体现了多态性。
1.2 具体实现
在具体的代码实现中,我们希望各个需要组织起来的类能够比较清晰的区分出来,所以在实现不同相对应的功能类时,我们会用不同意义的包将他们组织起来,使得各个包中只存放与当前包相关的功能类。
1.2.1 Book
和BookList
在我们思考图书管理系统的构建时,首先需要我们确定的一定是图书相关的信息,毕竟没有书怎么能够称为图书管理系统呢?
对于一本书而言,名称、作者、小说类型、价格以及书本的借阅状态都是需要定义的。
Book:
//Book.java
package book;//属于book包下的类
public class Book {
private String name;
private String author;
private String type;
private String price;
private boolean isBorrow;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.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 String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public boolean isBorrow() {
return isBorrow;
}
public void setBorrow(boolean borrow) {
isBorrow = borrow;
}
public Book(String name,String author,String type,String price) {
this.name = name;
this.author = author;
this.type = type;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", type='" + type + '\'' +
", price=" + price +
", " + (isBorrow ? "已借出" : "未借出") +
'}';
}
}
在定义完一本书的相关信息之后,我们会将这本书放到我们图书管理系统的书架上,借由书架来管理我们的图书,如图书管理系统上面存放的有效图书数量,以及书架中已拥有的图书信息。
BookShelf:
//BookShelf.java
package book;
public class BookShelf {
//顺序表
private Book[] books;
private int size;//记录有效个数
//构造方法初始化、存放初始书
public BookShelf() {
this.books = new Book[10];
this.books[0] = new Book("三国演义","罗贯中","小说", "31元");
this.books[1] = new Book("红楼梦","曹雪芹","小说", "27元");
this.books[2] = new Book("西游记","吴承恩","小说", "52元");
this.size = 3;
}
public void setSize(int size) {
this.size = size;
}
public int getSize() {
return this.size;
}
public Book[] getBooks() {
return books;
}
public void setBooks(Book[] books) {
this.books = books;
}
// public void setBook(Book book,int pos) {
// books[pos] = book;
// }
// public Book getBook(int pos) {
// return books[pos];
// }
}
1.2.2 User
、Administrator
和RegularUser
在定义好图书相关信息后,根据不同用户具有的不同权限我们设计了管理员和普通用户来对应拥有的不同权限,考虑到都是人为对图书进行操作和对不同用户(管理员和普通用户的区别)共性的抽取,我们可以将User
类设计为抽象类作为不同用户的父类实现多态。
User:
//User.java
package user; //属于user包下的类
import book.BookShelf;
import ioperation.IOperation;
public abstract class User {
protected String userName;
protected IOperation[] iOperations; //操作权限
public User(String userName) {
this.userName = userName;
}
public String toString() {
return "User{ " +
"userName = ' " + this.userName + '\'' +
"} ";
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return this.userName;
}
public abstract int menu();
//对图书进行的操作
public void doOperation(BookShelf bookShelf,int choice) {
iOperations[choice].doWork(bookShelf);
}
}
注意:前面提到我们会根据不同权限的用户开放不同的功能,也就是根据不同权限的用户展现不同的界面,所以我们在抽象类中定义抽象方法menu()方法交由不同用户根据不同需求实现不同界面信息。
Administrator:
//Administrator.java
package user;
import ioperation.*;
import java.util.Scanner;
public class Administrator extends User{
//private String passWord;
public Administrator(String userName) {
super(userName);
//初始化管理员的操作权限
this.iOperations = new IOperation[]{
new ExitOperation(),
new FindOperation(),
new AddOperation(),
new RemoveOperation(),
new ShowOperation()
};
}
//管理员菜单
public int menu() {
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.println("请输入你的操作:");
Scanner scanner = new Scanner(System.in);
int choice;
do {
choice = scanner.nextInt();
if(!(choice >= 0 && choice <= 4)) {
System.out.println("操作错误,请重新输入:");
}
}while(!(choice >= 0 && choice <= 4 ));
return choice;
}
}
RegularUser:
//RegularUser.java
package user;
import ioperation.*;
import java.util.Scanner;
public class RegularUser extends User{
public RegularUser(String userName) {
super(userName);
//初始化普通用户的操作权限
this.iOperations = new IOperation[]{
new ExitOperation(),
new FindOperation(),
new BorrowOperation(),
new ReturnOperation()
};
}
//普通用户菜单
@Override
public int menu() {
System.out.println("*****普通用户菜单*****");
System.out.println("1. 查找图书 ");
System.out.println("2. 借阅图书 ");
System.out.println("3. 归还图书 ");
System.out.println("0. 退出系统 ");
System.out.println("*******************");
System.out.println("请输入你的操作:");
Scanner scanner = new Scanner(System.in);
int choice;
do {
choice = scanner.nextInt();
if(!(choice >= 0 && choice <= 3)) {
System.out.println("操作错误,请重新输入:");
}
}while(!(choice >= 0 && choice <= 3 ));
return choice;
}
}
1.2.3 操作图书相关的功能类
对于对图书进行操作的功能类,我们注意到这些功能都是人为对图书进行的操作,也就是说我们可以定义一个公用的操作接口,用来规范、统一这些功能类,即定义公用接口实现共有方法(针对图书操作)doWork()。
IOperation:是统一规范的接口
//IOperation.java
package ioperation; //属于ioperation包下
import book.BookShelf;
//接口存放统一规范
public interface IOperation {
void doWork(BookShelf bookShelf);
}
1. AddOperation
//AddOperation.java
package ioperation;
import book.Book;
import book.BookShelf;
import java.util.Arrays;
import java.util.Scanner;
public class AddOperation implements IOperation{
@Override
public void doWork(BookShelf bookShelf) {
System.out.println("新增图书.....");
//新增图书
//判断是否需要扩容
Book[] books = bookShelf.getBooks();
int size = bookShelf.getSize();//有效存放长度
//扩容
if(books.length == size) {
bookShelf.setBooks(Arrays.copyOf(books,size*2));
}
//插入新图书
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("请输入价钱:");
String price = scanner.nextLine();
Book newBook = new Book(name,author,type,price);
//判断书架中有无这本书
for (int i = 0; i < size; i++) {
if(books[i].getName().equals(name)) {
System.out.println("书架中已存在这本书");
return ; }
}
books[size] = newBook;
bookShelf.setSize(size+1);//改变书本有效长度
System.out.println("新增图书成功");
}
}
需要注意的是:新增图书功能中,应该先判断图书是否已经存在以及书架上图书数量的维护,其次再进行新增图书的功能。
2. BorrowOperation
//BorrowOperation.java
package ioperation;
import book.Book;
import book.BookShelf;
import java.util.Scanner;
public class BorrowOperation implements IOperation{
@Override
public void doWork(BookShelf bookShelf) {
System.out.println("借阅图书.....");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要借阅的书名:");
String name = scanner.nextLine();
Book[] books = bookShelf.getBooks();
for (int i = 0; i < bookShelf.getSize(); i++) {
if(books[i].getName().equals(name)) {
System.out.println("找到这本书");
if(!books[i].isBorrow()) {
books[i].setBorrow(true);
System.out.println("借阅成功");
}else {
System.out.println("这本书已借出");
}
return ;
}
}
System.out.println("没有你要借阅的这本书");
}
}
借阅图书需要注意是否借阅成功以及借阅后借阅状态的修改
3. ExitOperation
//ExitOperation.java
package ioperation;
import book.BookShelf;
public class ExitOperation implements IOperation{
@Override
public void doWork(BookShelf bookShelf) {
System.out.println("退出系统.....");
System.exit(0);
}
}
4. FindOperation
//FindOperation.java
package ioperation;
import book.Book;
import book.BookShelf;
import java.util.Scanner;
public class FindOperation implements IOperation{
@Override
public void doWork(BookShelf bookShelf) {
System.out.println("查找图书.....");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要查找的书名:");
String name = scanner.nextLine();
Book[] books = bookShelf.getBooks();
for (int i = 0; i < bookShelf.getSize(); i++) {
if(books[i].getName().equals(name)) {
System.out.println("查找到这本书");
System.out.println(books[i]);
return ; }
}
System.out.println("没有你要找的书.....");
}
}
5. RemoveOperation
//RemoveOperation.java
package ioperation;
import book.Book;
import book.BookShelf;
import java.util.Scanner;
public class RemoveOperation implements IOperation{
@Override
public void doWork(BookShelf bookShelf) {
System.out.println("删除图书.....");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要删除的书名:");
String name = scanner.nextLine();
Book[] books = bookShelf.getBooks();
int pos = -1;
int size = bookShelf.getSize();
for (int i = 0; i <size; i++) {
if(books[i].getName().equals(name)) {
//可以根据图书是否归还来确定是否可删除(可选)
/*if(book[i].isBorrowed()) {
System.out.println("删除失败,图书未归还");
return ;
}*/
System.out.println("找到这本书");
pos = i;
break; }
}
if(pos == -1) {
System.out.println("没有你要删除的书.....");
return ; }
for (int j = pos; j < size - 1; j++) {
Book tmp = books[j];
books[j] = books[j+1];
books[j+1] = tmp;
}
System.out.println("删除成功.....");
bookShelf.setSize(size - 1);
}
}
6. ReturnOperation
//ReturnOperation.java
package ioperation;
import book.Book;
import book.BookShelf;
import java.util.Scanner;
public class ReturnOperation implements IOperation{
@Override
public void doWork(BookShelf bookShelf) {
System.out.println("归还图书.....");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你要归还的书名:");
String name = scanner.nextLine();
Book[] books = bookShelf.getBooks();
for (int i = 0; i < bookShelf.getSize(); i++) {
if(books[i].getName().equals(name)) {
System.out.println("找到这本书");
if(books[i].isBorrow()) {
books[i].setBorrow(false);
System.out.println("归还成功");
}else {
System.out.println("这本书未借出");
}
return ;
}
}
System.out.println("你要归还的这本书不是我们的");
}
}
7. ShowOperation
//ShowOperation.java
package ioperation;
import book.Book;
import book.BookShelf;
public class ShowOperation implements IOperation{
@Override
public void doWork(BookShelf bookShelf) {
System.out.println("显示图书.....");
Book[] books = bookShelf.getBooks();
for (int i = 0; i < bookShelf.getSize(); i++) {
System.out.println(books[i]);
}
System.out.println("显示图书成功.....");
}
}
1.2.4 测试程序的测试类
用于实现书架的初始化,以及对不同选项所指引的登录用户进行处理的类Test
。
import book.BookShelf;
import user.Administrator;
import user.RegularUser;
import user.User;
import java.util.*;
public class Test {
public static void main(String[] args) {
//利用基础语法知识写一个Library management system
//对象:用户、书、书架间的交互
//功能(基础)需求:实现不同用户面对图书的不同功能
//增删查改、借阅、归还等
//要求:体现一定封装性、多态、继承等,考虑抽象类、接口以及异常的使用
//创建书架
BookShelf bookShelf = new BookShelf();
//登录
User user = null;
do {
user = logIn();
}while(user == null);
while(true) {
int choice = user.menu();//向上转型、多态、动态绑定
user.doOperation(bookShelf,choice);
}
}
public static User logIn() {
//这个方法中实现身份的确定
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的用户名:");
String userName = scanner.nextLine();
System.out.println("请选择你的身份:1. 管理员 2. 普通用户");
int choice = scanner.nextInt();
if (choice == 1) {
return new Administrator(userName);
} else if (choice == 2) {
return new RegularUser(userName);
} else {
System.out.println("操作错误,请重新选择:");
}
return null;
}
}
在logIn()方法中实现对登录操作的处理,通过不同的选项返回不同权限的用户进而实现身份的选择。
用SE语法实现的图书管理系统实际上是对我们SE基础语法知识内容的整合,在实现过程中加深我们对类的封装性、多态性以及各个语法知识点的联合应用的认识。