一.整体框架
我们采取面向对象的编程思想,将整个图书管理系统抽象出多个对象,然后通过各个对象之间的交互来完成我们的整体设计需求
我们整体的设计框架如下图:
我们通过抽取他们的共性做出以下设计:
- 我们的书籍放在书架上,因此他们处于同一个包内
- 我们的增删查改的操作都是属于用户对图书的操作,因此他们处于同一个包内,这样也更方便不同用户来调用这些操作
- 用户分为普通用户和管理员用户,他们都是对于图书管理系统的直接操作者,因此他们处于同一个包中
对应我们上述结构图我们如下设计:
二.书籍和书架
书籍(Book)
我们应该提供书籍的相关信息:
- 书名
- 作者
- 价格
- 书籍类型
- 借阅状态
为了体现面向对象的封装特性,我们将这些字段信息设为 private 然后再设置一些 public 的方法以供给其他对象访问
package BookRack; //书籍 public class Book { private String name;//书名 private String author;//作者名 private int price;//价格 private String type;//书的类型 private boolean isBorrowed;//是否已经被借出 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; } //构造方法初始化 public Book(String name, String author, int price, String type) { //图书默认没有借出,所以isBorrowed默认false,不需要初始化 this.name = name; this.author = author; this.price = price; this.type = type; } //方便我们打印整个书籍的全部信息 @Override public String toString() { return "Book.Book{" + "name='" + name + '\'' + ", author='" + author + '\'' + ", price=" + price + ", type='" + type + '\'' + '}'; } }
书架(BookRack)
书架主要是用来存放书籍的,因此我们只需要提供以下俩个信息就可以:
- 已经存放的书籍,也就是一个书籍数组,数组中每一个元素都是一本书籍对象
- 已经存放的书籍的数量
为了体现面向对象的封装性,我们还是将这些字段信息设为 private 然后再设置一些 public 的方法以供给其他对象访问,在这里我们实现再书架上存放三本书,因此在构造方法中做出相应的初始化
package BookRack; //书架 public class BookRack { private Book[] books;//存放的所有的书 private int uesdSize;//书架上已经放的书的数量 public BookRack() { this.books = new Book[10];//默认书架可以放10本书 this.books[0] = new Book("三国演义","罗贯中",20,"小说"); this.books[1] = new Book("西游记","吴承恩",9,"小说"); this.books[2] = new Book("红楼梦","曹雪芹",19,"小说"); this.uesdSize = 3;//默认书架上有3本书 } //拿到某个位置的书籍 public Book getBooks(int pos) { return books[pos]; } //设置某个位置的书籍 public void setBooks(Book book,int pos) { books[pos] = book; } public int getUesdSize() { return uesdSize; } public void setUesdSize(int uesdSize) { this.uesdSize = uesdSize; } }
三.对书籍的相关操作
操作接口(IOperation)
所有的操作都是要对于书架进行操作的,所以我们在这里提供一个接口供不同操作来实现,并且给他们传入书架类的参数
package Operation; import BookRack.BookRack; //操作接口 public interface IOperation { //我们的任何增删查改的操作都是对于书架进行操作的,所以传入的参数是书架类 void work(BookRack bookRack); }
新增图书(AddOperation)
首先,我们需要让用户输入想要添加的图书的相关信息,然后我们为用户输入的图书新建一个对象,接下来就是合法性判断,我们拿刚才新建的图书对象和书架上的每一个图书对象进行遍历对比,如果没有重复的图书就可以存入这本书,要存入这本书就调用刚才书架类中提供的方法setBooks,在新加一本书籍后,对应的书籍数量也得增加,也就是调用setUesdSize方法来增加书籍的数量
package Operation; import BookRack.BookRack; import BookRack.Book; import java.util.Scanner; public class AddOperation implements IOperation{ @Override public void work(BookRack bookRack) { 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(); System.out.println("请输入您要添加的图书的类型:"); String type = scanner.nextLine(); //因为我们的每一个书都是一个对象,书架是一个对象数组,我们新加图书的时候就应该新实例化一个对象 Book book = new Book(name,author,price,type); //合法性判断 int usedSize = bookRack.getUesdSize();//拿到当前书架内放了书的数量 for (int i = 0; i < usedSize; i++) { //遍历书架中的图书挨个对比名字是否相同 Book tempbook = bookRack.getBooks(i); if (tempbook.getName().equals(name)) { System.out.println("不能重复添加同一本书,请重试!"); return; } } //可以添加新的图书 bookRack.setBooks(book,usedSize); bookRack.setUesdSize(usedSize+1); } }
借阅图书(BorrowOperation)
首先,我们需要让用户输入想要添加的图书的相关信息,然后我们为用户输入的图书新建一个对象,然后我们挨个遍历书架上的书,如果有,那就可以借,将书籍的借阅状态改为true就可以,如果没有就告诉用户没有此书,无法借阅
package Operation; import BookRack.BookRack; import BookRack.Book; import java.util.Scanner; public class BorrowOperation implements IOperation{ @Override public void work(BookRack bookRack) { System.out.println("借阅图书操作进行中......"); System.out.println("请输入您想借阅的书名:"); Scanner scanner = new Scanner(System.in); String name = scanner.nextLine(); //遍历整个书架 for (int i = 0; i < bookRack.getUesdSize(); i++) { Book temp = bookRack.getBooks(i); if (name.equals(temp.getName())) { temp.setBorrowed(true); System.out.println("借阅成功!"); return; } } System.out.println("没有查询到您想要借阅的图书,请重新尝试!"); } }
删除图书(DeleteOperation)
首先,要删除图书的第一步应该是先找到这本书,因此我们像刚才借阅图书一样,先遍历整个书架找到这本书,然后记录这本书的位置,之后再利用书架提供的 setBooks 方法来存放这本书,如果没有找到那就告诉用户并且退出这个操作
package Operation; import BookRack.BookRack; import BookRack.Book; import java.util.Scanner; public class DeleteOperation implements IOperation{ @Override public void work(BookRack bookRack) { System.out.println("删除图书操作进行中......"); System.out.println("请输入您想删除的书名:"); Scanner scanner = new Scanner(System.in); String name = scanner.nextLine(); //要删除的前提是先找到这本书 int uesdSize = bookRack.getUesdSize(); int flag = -1; int i = 0; for (; i < uesdSize; i++) { Book tempbook = bookRack.getBooks(i); if (tempbook.getName().equals(name)) { //找到这本书 flag = i; break; } } if (i >= uesdSize) { System.out.println("查无此书,无法删除"); return; } //存在这本书,进行删除,也就是将书架中的书从后向前依次覆盖 for (int j = flag; j < uesdSize; j++) { Book tempbook = bookRack.getBooks(j+1);//拿到 j+1 位置的书 bookRack.setBooks(tempbook,j);//和 j 位置的书交换 } bookRack.setBooks(null,uesdSize-1);//将最后一个位置的图书置为空 bookRack.setUesdSize(uesdSize-1);//图书数量减一 System.out.println("删除成功!"); } }
查找图书(FindOperation)
查找图书就非常简单了,我们在刚才的删除图书操作中相当于已经完成了这部分操作了
package Operation; import BookRack.BookRack; import BookRack.Book; import java.util.Scanner; public class FindOperation implements IOperation{ @Override public void work(BookRack bookRack) { System.out.println("查找图书操作进行中......"); System.out.println("请输入您想查找的书名:"); Scanner scanner = new Scanner(System.in); String name = scanner.nextLine(); int usedSize = bookRack.getUesdSize(); for (int i = 0; i < bookRack.getUesdSize(); i++) { Book temp = bookRack.getBooks(i); if (name.equals(temp.getName())) { System.out.println("存在这本书,信息如下:"); System.out.println(temp); return; } } System.out.println("没有你要找的这本书,书名为:"+ name); } }
归还图书(ReturnOperation)
和我们的借阅图书操作相同,唯一不同的就是这里是将图书的借阅状态改为 false
package Operation; import BookRack.BookRack; import BookRack.Book; import java.util.Scanner; public class ReturnOperation implements IOperation{ @Override public void work(BookRack bookRack) { System.out.println("借阅图书操作进行中......"); System.out.println("请输入您想借阅的书名:"); Scanner scanner = new Scanner(System.in); String name = scanner.nextLine(); //遍历整个书架 for (int i = 0; i < bookRack.getUesdSize(); i++) { Book tempbook = bookRack.getBooks(i); if (name.equals(tempbook.getName())) { tempbook.setBorrowed(false); System.out.println("归还成功!"); return; } } System.out.println("没有你要归还的图书:"+name); } }
展示图书(ShowOperation)
遍历整个书架,然后挨个打印输出图书信息就可以了
package Operation; import BookRack.Book; import BookRack.BookRack; public class ShowOperation implements IOperation{ @Override public void work(BookRack bookRack) { System.out.println("图书列表如下:"); for (int i = 0; i < bookRack.getUesdSize(); i++) { Book tempbook = bookRack.getBooks(i); System.out.println(tempbook); } } }
退出系统(ExitOperation)
我们这里直接使用 exit 来结束整个程序就可以
package Operation; import BookRack.BookRack; public class ExitOperation implements IOperation{ @Override public void work(BookRack bookRack) { System.out.println("退出系统..."); System.exit(0); } }
四.用户部分
用户抽象类(User)
在普通用户和管理员用户中存在许多共性,因此我们这里设置一个抽象类供普通用户和管理员用户来继承使用
package Person; import BookRack.BookRack; import Operation.IOperation; public abstract class User { protected String name;//姓名 protected IOperation[] iOperations;//操作接口数组 public abstract int menu();//菜单 public User(String name) { this.name = name; } //供用户来选择操作,调用操作接口 public void doOperation(int choice, BookRack bookRack) { IOperation ioperation = iOperations[choice]; ioperation.work(bookRack); } }
管理员类(Administrator)
我们设置管理用户的菜单,再对应着菜单设置接口类型的数组的具体操作
package Person; import Operation.*; import java.util.Scanner; public class Administrator extends User { public Administrator(String name) { super(name); iOperations = new IOperation[]{ new ExitOperation(), new FindOperation(), new AddOperation(), new DeleteOperation(), 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 = scanner.nextInt(); return choice; } }
普通用户(NormalUser)
和管理员用户的设置一样,我们对应的存放接口数组中的操作就可以
package Person; import Operation.*; import Person.User; import java.util.Scanner; public class NormalUser extends User { public NormalUser(String name) { super(name); iOperations = new IOperation[]{ new ExitOperation(), new FindOperation(), new BorrowOperation(), new ReturnOperation() }; } 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 = scanner.nextInt(); return choice; } }
五.main方法(Test)
我们再这里设置一个登录程序,登录管理员我们就新建一个管理员对象,登录普通用户我们就新建一个普通用户对象,然后我们根据用户的输入来调用我们菜单中的选项,也就是我们刚才设置的接口操作数组中的操作
import BookRack.BookRack; import Person.Administrator; import Person.NormalUser; import Person.User; import java.util.Scanner; public class Test { public static User login() { System.out.println("请输入您的名字:"); Scanner scanner = new Scanner(System.in); String name = scanner.nextLine(); System.out.println("请确认您的身份:"); System.out.println("1.管理员"); System.out.println("2.普通用户"); int choice = scanner.nextInt(); if (choice == 1) { return new Administrator(name); }else{ return new NormalUser(name); } } public static void main(String[] args) { BookRack bookRack = new BookRack(); User user = login();//向上转型 while (true) { int choice = user.menu(); user.doOperation(choice, bookRack); } } }
完整代码:
按照笔者这里对应的包和类的设置进行操作就可以,每一个类和包在上文中都完整给出来了
如果觉得麻烦的话,笔者这里给出对应的码云,大家有需要自取
LibrarySystem · 鹿鸣/JavaSE