hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥💥,如果发现这篇文章有问题的话,欢迎各位评论留言指正,大家一起加油!一起chin up!👍👍
现在我们将把之前学过的知识点总结做成一个小项目 ,叫图书管理系统,来看一下吧。
我们在设计系统前要遵循面向对象的原则: 1.找到对象 2.创建对象 3.使用对象 所以我们需要先理清自己的思绪,想明白需要创建的对象和需要实现的功能。 1. 首先,想清楚系统的界面。系统对于图书管理员来说是管理系统,对于普通用户来说是服务系统。所以我们针对管理员和普通用户所展示的界面是不同的。 2.书的属性有书名,作者,价格,类型,是否被借出。所以我们可以将书的属性进行封装,同时设置一个书架类,用于存放书籍。设置一个书的数组可以解决。 3.管理员界面上,我们可以添加书籍,查找书籍,删除书籍,显示书籍和退出系统。 4.普通用户界面上,我们可以查找书籍,借阅书籍,归还书籍和退出系统。 5.所以我们可以将这些操作封装起来,设计成单独的类,但可以通过一些操作将这些功能分成两部分。
❤️❤️首先我们面对对象时,找对象书肯定是一个对象,所以我们创建跟书有关的对象,如书和书架。现在我们就先来创建这两个对象吧:
❤️❤️我们创建一个book的包,用于存放与书有关的类。根据上述思路,我们可以在Book包中创建一个Book的类和一个Booklist (书架) 的类。首先创建一个book类,在book中写入书的有关属性,书名 (name) ,作者 (author) ,价格 (price) ,类型 (type) 以及是否被借出。我们通过封装,将属性前的访问修饰符设置为private权限,然后通过提供相应的get方法和set方法以及一个不包含是否被借出的构造方法(我们将是否被借出属性的类型设置为boolean,因为Boolean类型默认为false,所以可以不初始化),然后通过快捷键提供相应的toString方法的重写。
注意这些方法很多都能通过快捷键去生成,代码如下:
public class Book {
private String name;
private String author;
private String type;
private int price;
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 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;
}
之所以用private修饰其书的属性,是为了体现书的密封性(书架中的属性也同理)
💕💕我们首先设置一个private权限的Book数组books,同时设置一个usedSize的变量,用于记录当前书架上存放了多少本书。我们写一个BookList的构造方法,同时将数组的长度初始化为10,然后通过快捷键设置userSize的getter and setter方法。注意不要使用编译器生成的Book数组books的getter and setter 方法,因为它针对的是books数组,并不是针对数组中存放的书,那并不是我们想要的。所以我们单独设置一个名为pos的数组下标参数,在getter方法中返回books的数组下标pos,在setter方法中,我们将 books数组的pos下标设置为一本书 。这样就能通过这两个方法去访问该数组的书成员。
现在请看以下代码:
public class BookList {
private Book[] books;
private int usedsize;//书架上目前存放的书量
public BookList() {
this.books=new Book[10];
usedsize=4;
this.books[0] = new Book("三国演义","罗贯中",20,"小说");
this.books[1] = new Book("西游记","吴承恩",9,"小说");
this.books[2] = new Book("红楼梦","曹雪芹",19,"小说");
this.books[3]=new Book("Java","xx",18,"学习资料");
}
public int getUsedsize() {
return usedsize;
}
public void setUsedsize(int usedsize) {
this.usedsize = usedsize;
}
public Book getBook(int i){
return books[i];
}
public void setBook(int i,Book book){
books[i]=book;
}
}
这里的属性也是用private修饰,呈封装性。
💕💕 除此之外,除了书是对象,图书管理系统也要人使用对吧,所以人也是个对象。并且因为身份的不同,分为普通用户和管理员。而又因为都是人,所以会有一些相同点。所以我们就创建一个子类user ,两个父类。
💕💕在普通用户和管理员用户中存在许多共性,因此我们这里设置一个抽象类供普通用户和管理员用户来继承使用,并且将其变为抽象类更方便继承。
abstract public class User {
protected String name;
protected IOperation[] iOperations;
abstract public int menu();
public User(String name) {
this.name = name;
}
public void useoperation(int choice,BookList bookList){
IOperation iOperation = iOperations[choice];
iOperation.work(bookList);
}
}
💕💕我们设置管理用户的菜单,再对应着菜单在构造方法中设置接口类型的数组的具体操作
public class Administrator extends User{
public Administrator(String name) {
super(name);
iOperations = new IOperation[]{
new ExitOperation(),
new FindOperation(),
new AddOperation,
new DeleteOperation(),
new ShowOperation()
};
}
@Override
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;
}
}
💕💕它和管理员类的操作大致相同,这里就不过多讲述了,直接上代码
public class NormalUser extends User {
public NormalUser( String name){
super(name);
iOperations=new IOperation[] {
new ExitOperation(),
new FindOperation(),
new BorrowOperation(),
new RetrunOperation()
};
}
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;
}
}
❤️❤️我们知道面对对象分为三步,最后一步是使用对象,而这里就是对于对象的使用。其中有很多操作,我们来看一下吧。
❤️❤️所有的操作都是要对于书架进行操作的,所以我们在这里提供一个接口供不同操作来实现,并且给他们传入书架类的参数,代码如下:
public interface IOperation {
public void work(BookList bookList);
}
❤️❤️首先,我们需要让用户输入想要借阅的图书的名字,然后我们挨个遍历书架上的书,如果有,那就可以借,将书籍的借阅状态改为true就可以,如果没有就告诉用户没有此书,无法借阅。
public class BorrowOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("该操作进行中,请输入要借阅的书");
Scanner scanner=new Scanner(System.in);
String name =scanner.nextLine();
for (int i = 0; i < bookList.getUsedsize() ; i++) {
if ((bookList.getBook(i).getName()).equals(name)){
if(bookList.getBook(i).getIsborrowed()==true) {
System.out.println("该书已被借出,现在没有这本书");
return;
}else {
System.out.println("该书借出后请及时归还");
bookList.getBook(i).setIsborrowed(true);
return;
}
}
if(i== bookList.getUsedsize()-1){
System.out.println("未查找到该书");
}
}
}
}
❤️❤️和借阅图书思路相似,这里不多说了。直接上代码:
public class RetrunOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("该操作进行中,请输入要归还的书");
Scanner scanner=new Scanner(System.in);
String name =scanner.nextLine();
for (int i = 0; i < bookList.getUsedsize() ; i++) {
if ((bookList.getBook(i).getName()).equals(name)) {
bookList.getBook(i).setIsborrowed(false);
System.out.println("该书归还成功");
return;
}
}
System.out.println("不存在该书");
}
}
❤️❤️ 查找功能和遍历类似,只要利用equals关键字比较字符串输出就行。在 Findioperation 类中,先输入要查找的书名,遍历所有的书,比较书名,书名一样输出即可。
public class FindOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("该操作进行中,请输入要查找的书");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
for (int i = 0; i < bookList.getUsedsize(); i++) {
if ((bookList.getBook(i).getName()).equals(name)) {
System.out.println("找到该书");
System.out.println(bookList.getBook(i));
return;
}
}
System.out.println("没找到该书");
}
}
❤️❤️ 遍历整个书架,然后挨个打印输出图书信息就可以了。
public class ShowOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("该操作进行中,将展示所有书的信息");
for (int i = 0; i < bookList.getUsedsize() ; i++) {
System.out.println(bookList.getBook(i));
}
}}
❤️❤️首先,我们需要让用户输入想要添加的图书的相关信息,然后我们为用户输入的图书新建一个对象,接下来就是合法性判断,我们拿刚才新建的图书对象和书架上的每一个图书对象进行遍历对比,如果没有重复的图书就可以存入这本书,要存入这本书就调用刚才书架类中提供的方法setBooks,在新加一本书籍后,对应的书籍数量也得增加,也就是调用setUesdSize方法来增加书籍的数量。
public class AddOperation implements IOperation {
@Override
public void work(BookList bookList) {
System.out.println("该操作进行中,请输入要添加的书");
Scanner scanner = new Scanner(System.in);
System.out.println("请输入书名");
String name = scanner.nextLine();
if(bookList.getUsedsize()==10) {
System.out.println("书架满了,无法添加");
return;
}
for (int i = 0; i < bookList.getUsedsize(); i++) {
if ((bookList.getBook(i).getName()).equals(name)) {
System.out.println("该书在书架中已有,无需添加");
return;
}}
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,price,type);
bookList.setBook(bookList.getUsedsize(),book );
System.out.println("添加成功");
bookList.setUsedsize(bookList.getUsedsize()+1);
}}
这里有个重要的点,对于新建对象时的输入,必须nextint在最后面,否则会导致以下现象。
这里只接受了三个,第四个还没输入就结束了。所以应该把nextint放在最后,这样就不会有异常现象。
对于其原因,这里有篇文章可以解释以上现象java中程序逻辑控制-CSDN博客,在这部分有提到过该现象。
❤️❤️思路:首先找到有没有这本书,如果找到了,这书后边的书就从后往前直接覆盖掉之前的书数据,然后将usedsize减一就行了,从而最后一个数据我们就使用不了(之后的其他操作会将最后一个数据覆盖掉)。
所以在循环时,i 要小于usedSize - 1,,如果大于等于usedsize-1的话,就会越界访问数组之外的数据,从而报错。
public class DeleteOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("该操作进行中,请输入要删除的书");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
int deletesize=0;
for (int i = 0; i < bookList.getUsedsize(); i++) {
if ((bookList.getBook(i).getName()).equals(name)) {
deletesize=i;
break;
}
if(i== bookList.getUsedsize()-1)
{
System.out.println("该书架中不存在该书");
return;
}
}
for (int i = deletesize; i < bookList.getUsedsize()-1 ; i++) {
bookList.setBook(i,bookList.getBook(i+1));
}
bookList.setUsedsize(bookList.getUsedsize()-1);
System.out.println("删除"+name+"成功");
}}
❤️❤️最简单的一个操作,System.exit(0)代表着结束程序,所以我们只需要使用该方法就能退出系统。
public class ExitOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("系统已退出");
System.exit(0);//作用是结束该程序
}
}
所以有了前面的这些基础,我们就将它们组合起来利用,形成这个main类。
我们在main类中除了有main方法外,还要设置一个登录程序的方法,登录管理员我们就新建一个管理员对象,登录普通用户我们就新建一个普通用户对象,然后我们根据用户的输入来调用我们菜单中的选项,我们通过设置接口数组从而来操作它。
public class Main {
public static User login() {
System.out.println("请输入你的名字");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("请确认你的身份 1:普通用户 2:管理员 ");
while (true) {
int choice = scanner.nextInt();
if (choice == 1) {
return new NormalUser(name);
} else if (choice == 2) {
return new Administrator(name);
} else {
System.out.println("只能输入1或2,请重新输入");
continue;
}
}
}
public static void main(String[] args) {
BookList bookList=new BookList();
User user =login();
while (true){
int choice= user.menu();
user.useoperation(choice,bookList);
}
}