目录
展示样例
第一步:输入用户名及用户权限
第二步:展示菜单
第三步:输入具体执行操作
第四步:退出程序
初步实现:建立package文件夹以及其中的类
由上图的过程我们可以看出,若要展示书籍,我们需要一个书籍包,具体的书类和一个存放书的书架类
若要完成各种操作,我们需要一个操作包,包含一个接口作为操作总接口,包含一个操作子包,子包中包含继承它的各种操作,也就是接口的子类
若要输入用户名以及判断权限,我们需要一个用户包,一个总的用户类,以及继承它的两种用户,普通用户和管理员。
最后需要一个把程序跑起来的Main文件
初步实现:book包
Book类
Book类构思
我们首先定义Book类中的几个属性:书名,作者,价钱,类型,是否借阅
作为内部类,设为私有即可。
然后我们需要一个有参构造方法可以在建立Book类传参的时候赋值。
所有的类型都可以用来查看,所以getter所有的属性。
需要更改的属性应该是价钱,类型,以及是否借阅。所以我们需要提供它们的setter方法。
具体代码实现
package book_management.book;
/**
* 书本类
* @author DELL
* @date 2022-05-09 23:18
*/
public class Book {
//书名
private String name ;
//作者名
private String author;
//书籍价格
private Double price;
//书籍的类别
private String type;
//书籍是否被借出,默认为false
private boolean isBorrowed;
public Book(String name, String author, Double price, String type) {
this.name = name;
this.author = author;
this.price = price;
this.type = type;
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
public Double getPrice() {
return price;
}
public String getType() {
return type;
}
public boolean getBorrow() {return isBorrowed ;}
public boolean isBorrowed() {
return isBorrowed;
}
public void setPrice(Double price) {
this.price = price;
}
public void setType(String type) {
this.type = type;
}
public void setBorrowed(boolean borrowed) {
isBorrowed = borrowed;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", type='" + type + '\'' +
", isBorrowed=" + isBorrowed +
'}';
}
}
BookList类初步实现
BookList类构思
我们先把书放到书架上,因为后续还需要书架提供方法,所以只能初步实现。
首先,我们需要一个books的动态数组存放具体书本类,由于后续可能再添加或者删除书籍所以用动态数组。
需要一个book动态数组存放书名,相当于一个书架具体书的索引的作用,方便查看书是否存在。
代码实现:
public class BookList {
//书架保存书籍,书本的个数不确定,用动态数组或者链表
private List<Book> books = new ArrayList<>();
private List<String> bookNames = new ArrayList<>();
public BookList() {
//产生一个书架对象时,默认上架的四本书籍
books.add(new Book("三国演义", "罗贯中", 66.6, "小说"));
books.add(new Book("水浒传", "施耐庵", 55.6, "小说"));
books.add(new Book("西游记", "吴承恩", 44.6, "小说"));
books.add(new Book("红楼梦", "曹雪芹&未知", 8.6, "小说"));
bookNames.add("三国演义");
bookNames.add("水浒传");
bookNames.add("西游记");
bookNames.add("红楼梦");
}
初步实现:operation包
IOperation接口
构思
我们只需要设定一个work方法即可,此方法可以继承到子类中去,work方法的内部实现的其实是BookList类提供的方法,我们建立这些子类的目的仅仅是因为用户的权限不同而衍生出来不同的类,最多来负责传入一些参数,而具体的改变书架的方法还是需要BookList本身去实现的。
另外 我们可以先建立一个Scanner引用,方便后续用户的输入,不至于在每个子类中都要重新建立引用。
代码实现
package book_management.operation;
import book_management.book.BookList;
import java.util.Scanner;
/**
* 操作书籍的接口
* @author DELL
* @date 2022-05-09 23:51
*/
public interface IOperation {
Scanner scanner = new Scanner(System.in);
//在指定的书架上进行操作处理
void work(BookList booklist);
}
初步实现Impl子包及各种操作类
因为是初步实现我们只需要建立几个操作类并继承IOperation接口即可,具体方法要和BookList配合使用。
初步实现:User包
User抽象类
构思
String name, 首先User类提供了姓名,protect权限,只有子类用的到。
定义一个数组:IOperation[ ] , User类主要是对权限做一个分割处理,每个User子类可以进行的operation操作是不一样的,所以我们需要定义一个operation的数组,将来每个User子类独有的这个数组是不同的,也就可以将权限区分开来。由于User子类才需要这个数组,所以采用protect权限。
定义一个菜单方法:menu ,也是因为子用户的权限不同所以菜单也需要不同,只能在子类中覆写,而且此方法返回一个 int 类型 ,这个返回值就代表了要进行的操作。
定义一个方法:doOperation, 我们可以在User类中选择要进行的操作,操作的也就是operation这个数组了。public权限,因为在外部要用
package book_management.user;
import book_management.book.BookList;
import book_management.operation.IOperation;
/**
* @author DELL
* @date 2022-05-09 23:44
*/
public abstract class User {
//用户名
protected String name;
//对于书籍的操作权限,此时不确定用户类型,所以是个空数组,由子类确定到底具备哪些权限
protected IOperation[] operations;
public User(String name){
this.name=name;
}
//菜单,不同种类的用户菜单是不同的,根据菜单的返回值取得用户选择的操作
public abstract int menu();
//
public void doOperation(BookList bookList,int choice) {
operations[choice-1].work(bookList);
}
}
子类:NormalUser和AdminUser类
构思:
用构造方法传参直接改变父类的name
覆写父类User的各种方法 :
1.建立operation数组,存放不同权限的具体操作方法
2.建立不同菜单,并且需要用户输入并返回要进行的操作
代码实现:
package book_management.user;
import book_management.operation.IOperation;
import book_management.operation.impl.*;
import org.omg.CORBA.PUBLIC_MEMBER;
import java.util.Scanner;
/**
* @author DELL
* @date 2022-05-10 0:47
*/
public class AdminUser extends User{
public AdminUser(String name) {
super(name);
operations = new IOperation[] {
new ListAllBookOperation(),
new AddOperation(),
new RemoveOperation(),
new UpdateOperation(),
new FindOperation()
};
}
@Override
public int menu() {
System.out.println("===================================");
System.out.println("欢迎"+this.name+"登录火箭图书管理系统");
System.out.println("1.显示当前的书籍列表");
System.out.println("2.增加书籍");
System.out.println("3.下架书籍");
System.out.println("4.更新书籍");
System.out.println("5.寻找书籍");
System.out.println("-1.退出系统");
System.out.println("==================================");
System.out.println("请输入您的选择");
Scanner scan = new Scanner(System.in);
int choice = scan.nextInt();
return choice;
}
}
具体实现:操作方法
整体构思:
具体的操作类以及BookList类配合起来使用即可达到此目的。
这两个类之间不太好分开说,总的来说就是操作类负责传入参数,来调用BookList提供的方法使BookList内部发生改变。
有两个方法比较特殊,一个是查看书籍是否存在,另外一个是找到书籍的方法,直接上图,大伙自己斟酌斟酌。
代码实现:
BookList类:
package book_management.book;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**书架类
* @author DELL
* @date 2022-05-09 23:33
*/
public class BookList {
//书架保存书籍,书本的个数不确定,用动态数组或者链表
private List<Book> books = new ArrayList<>();
private List<String> bookNames = new ArrayList<>();
public BookList() {
//产生一个书架对象时,默认上架的四本书籍
books.add(new Book("三国演义", "罗贯中", 66.6, "小说"));
books.add(new Book("水浒传", "施耐庵", 55.6, "小说"));
books.add(new Book("西游记", "吴承恩", 44.6, "小说"));
books.add(new Book("红楼梦", "曹雪芹&未知", 8.6, "小说"));
bookNames.add("三国演义");
bookNames.add("水浒传");
bookNames.add("西游记");
bookNames.add("红楼梦");
}
//展示书籍方法
public void listBooks() {
for (Book book : books) {
System.out.println(book);
}
}
//检验书籍是否存在
public boolean contains(String name) {
for (String bookName : bookNames) {
if (bookName.equals(name)) {
return true;
}
}
return false;
}
//添加书籍方法
public void addBooks(String name, String author, Double price, String type) {
books.add(new Book(name, author, price, type));
bookNames.add(name);
}
//查找书籍方法
public void findBook(String name) {
Book book = findListBook(name);
System.out.println(book);
}
//删除书籍方法
public void removeBook(String name) {
Book book = findListBook(name);
books.remove(book);
}
//借阅书籍方法
public void borrowBooks(String name) {
Book book = findListBook(name);
if(!book.getBorrow()) {
book.setBorrowed(true);
System.out.println("借阅书籍成功");
}
else {
System.out.println("此书已借阅");
}
}
//归还书籍方法
public void returnBooks(String name) {
Book book = findListBook(name);
if(book.getBorrow()) {
System.out.println("归还书籍成功");
book.setBorrowed(false);
} else {
System.out.println("此书未借阅,无法归还");
}
}
//更新书籍方法
public void updateBook(String name,String type,Double price) {
Book book = findListBook(name);
book.setPrice(price);
book.setType(type);
}
//找书本实体方法
public Book findListBook(String name) {
for(Book book : books) {
if(book.getName().equals(name)) {
return book;
}
}
throw new NoSuchElementException("未找到此书籍");
}
}
operation子类
我只贴出其中两个,后面的大差不差,基本一样
package book_management.operation.impl;
import book_management.book.BookList;
import book_management.operation.IOperation;
/**增加书籍
* @author DELL
* @date 2022-05-10 0:33
*/
public class AddOperation implements IOperation {
@Override
public void work(BookList booklist) {
System.out.println("您现在进行的是添加图书操作");
System.out.println("请输入要添加的书籍名称");
String bookName = scanner.nextLine();
if(!booklist.contains(bookName)) {
System.out.println("请输入作者");
String author = scanner.nextLine();
System.out.println("请输入类型");
String type = scanner.nextLine();
System.out.println("请输入价格");
Double price = scanner.nextDouble();
booklist.addBooks(bookName,author,price,type);
System.out.println("添加书籍成功");
} else {
System.out.println("书籍"+bookName+"已存在");
}
}
}
package book_management.operation.impl;
import book_management.book.BookList;
import book_management.operation.IOperation;
/**下架书籍
* @author DELL
* @date 2022-05-10 0:34
*/
public class RemoveOperation implements IOperation {
@Override
public void work(BookList booklist) {
System.out.println("现在您进行的是删除书籍操作");
System.out.println("请输入您要删除的书籍");
String bookName = scanner.nextLine();
if(booklist.contains(bookName)) {
booklist.findBook(bookName);
System.out.println("书籍删除成功");
} else {
System.out.println("未找到此书籍");
}
}
}
Main程序入口的实现
构思:
首先需要一个BookList的对象,然后需要模拟登录操作,在登录操作中,我们可以确定用户姓名,以及创建的是哪一种用户,最后当我们知道了操作权限,我们便可以进入操作的循环,并且在给定的输入中结束程序。
代码实现:
package book_management;
import book_management.book.BookList;
import book_management.user.AdminUser;
import book_management.user.NormalUser;
import book_management.user.User;
import java.util.NoSuchElementException;
import java.util.Scanner;
/**
* 程序的入口
* @author DELL
* @date 2022-05-10 0:40
*/
public class Main {
public static void main(String[] args) {
//1.此时图书馆只有一个书架
BookList bookList = new BookList();
//2.用户登录操作
User user = login();
//3.开始进行选择
while(true) {
int choice = user.menu();
if(choice== -1) {
System.out.println("bye!");
break;
}
user.doOperation(bookList,choice);
}
}
private static User login() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您的用户名");
String str = scanner.nextLine();
System.out.println("请输入您登录的角色,1表示普通用户,0表示管理员");
int choice = scanner.nextInt();
if(choice==1) {
return new NormalUser(str);
} else if(choice == 0){
return new AdminUser(str);
}
throw new NoSuchElementException("输入有误,没有这个选项");
}
}