Java面向对象编程(Object-Oriented Programming,OOP)是Java语言的核心特性之一,它提供了一种组织代码的方法,将现实世界中的事物抽象为对象,并通过对象之间的交互来构建程序。Java面向对象编程包含以下主要概念:
类和对象(Class and Object):
类是面向对象编程的基本构建块,它是对一组具有相同属性和行为的对象的抽象描述。对象是类的实例化结果,它是内存中的实体,具有类所定义的属性和行为。类定义了对象的结构和行为,而对象则代表了真实世界中的具体实体。
封装(Encapsulation):
封装是一种将数据和行为封装在类中,阻止外部直接访问和修改对象的内部状态的特性。通过封装,类可以隐藏其实现细节,并通过公共的方法提供对内部状态的访问和操作。这有助于提高代码的可维护性和安全性。
继承(Inheritance):
继承是一种类之间的关系,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和行为。子类可以复用父类的代码,并且可以在不修改父类的情况下增加新的功能。继承提供了代码重用和层次化组织的能力。
多态(Polymorphism):
多态是指同一操作可以在不同的对象上产生不同的结果。它允许我们使用统一的接口来处理不同类的对象,从而提高代码的灵活性和可扩展性。多态有两种形式:静态多态(方法重载)和动态多态(方法重写,也称为覆盖)。
抽象类(Abstract Class):
抽象类是不能被实例化的类,它用于作为其他类的基类,提供一种对类的抽象描述。抽象类可以包含抽象方法和具体方法,子类必须实现抽象方法才能被实例化。抽象类常常用来定义类的通用行为和属性。
接口(Interface):
接口是一种特殊的抽象类,它定义了一组抽象方法,但不包含具体的实现。类可以实现(implements)一个或多个接口,实现接口的类必须提供接口中定义的所有方法。接口提供了一种多继承的机制,使得类可以在不同的继承树上实现不同的功能。
确定系统的功能:明确图书管理系统的基本功能,如查找图书、新增图书、删除图书、显示图书、借阅图书、归还图书等功能。
定义用户角色和权限:确定系统中的用户角色,如读者、管理员等,并定义他们的权限和操作范围。
识别数据需求:分析需要存储的数据,如图书信息、读者信息、借阅记录等,并确定数据之间的关系。
根据需求分析,我们的图书管理系统有图书、用户、然后还有用户对图书的操作。所以我们先把这三个包创建好。
值得注意的是,我们可以定义一个IOperation接口,让所有的操作继承这个接口,之后只要是进行操作就只要调用这个接口就好了。另外我们的User类,实际上是一个抽象的概念,实际上我们是普通用户和管理员是实际的,所以我们可以定义一个抽象的User类,然后派生出具体的用户。最后,我们我们还要创建一个启动类,作为整个程序的入口。
package book;
/**
* @Author: Fourteen-Y
* @Description: 图书信息,包括书名、作者、价格、类型、是否被借出
* @Date: 2023/7/27 12:04
*/
public class Book {
// 图书的属性
private String name;
private String author;
private int price;
private String type;
private boolean isBorrowed;
// 图书的构造方法,实例对象的时候能直接定义图书对象
public Book(String name, String author, int price, String type) {
this.name = name;
this.author = author;
this.price = price;
this.type = type;
}
// getter和setter方法,图书的属性被声明为私有,提供公共的方法来让外部代码访问这些属性的值。
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;
}
// 重写toString方法,更好的打印图书信息
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
", type='" + type + '\'' +
// 三目运算符 当isBorrowed为true时,输出已借出,否则输出未借出
((isBorrowed == true) ? " ,已借出" : " ,未借出")+
// ", isBorrowed=" + isBorrowed +
'}';
}
}
package book;
/**
* @Author: Fourteen-Y
* @Description: 对图书的存储
* @Date: 2023/7/27 12:04
*/
public class BookList {
/**
* 创建一个数组,用来存放书籍,一开始默认5本书
*/
private static Book[] books = new Book[5];
/**
* 数组中放了书的个数
*/
private int usedSize;
/**
* 默认存放的书籍
*/
public BookList() {
books[0] = new Book("三国演义","罗贯中",34,"小说");
books[1] = new Book("西游记","吴承恩",24,"小说");
books[2] = new Book("红楼梦","曹雪芹",30,"小说");
books[3] = new Book("水浒传","施耐庵",34,"小说");
books[4] = new Book("西厢记","王实甫",34,"小说");
this.usedSize = 5;
}
public int getUsedSize() {
return usedSize;
}
public void setUsedSize(int usedSize) {
this.usedSize = usedSize;
}
//借书还书的操作,涉及到数组的操作
/**
* 获取pos下标的书
* @param pos
* @return
*/
public Book getPos(int pos) {
return books[pos];
}
/**
* 给数组的pos位置,放一本书
* @param pos
* @param book
*/
public static void setBooks(int pos, Book book) {
books[pos] = book;
}
}
package user;
import book.BookList;
import operation.IOperation;
/**
* @Author: Fourteen-Y
* @Description: 用户抽象类 有两个子类:普通用户和管理员
* @Date: 2023/7/27 12:10
*/
public abstract class User {
protected String name;
/**
* 把所有的操作都放到这个数组中 通过下标来选择具体的操作
*/
public IOperation[] ioPerations;
public User(String name) {
this.name = name;
}
public abstract int menu();
/**
* 根据用户输入的选项,调用对应的操作
* @param choice 用户输入的选项
* @param bookList 图书列表
*/
public void doOperation(int choice, BookList bookList) {
// work是所有操作的具体实现,传入要操作的书籍数组
ioPerations[choice].work(bookList);
}
}
package user;
import operation.*;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description: 管理员 1.查找图书 2.新增图书 3.删除图书 4.显示图书 0.退出系统
* @Date: 2023/7/27 12:09
*/
public class AdminUser extends User {
public AdminUser(String name) {
super(name);
// 把所有的操作在数组中new出来,
// 由于还没实现这些具体的操作,所以一下代码展示会报错
this.ioPerations = new IOperation[] {
new ExitOperation(),
new FindOperation(),
new AddOperation(),
new DelOperation(),
new DisplayOperation(),
};
}
/**
* 管理员菜单 1.查找图书 2.新增图书 3.删除图书 4.显示图书 0.退出系统
* @return 返回用户输入的选项,供主程序调用
*/
@Override
public int menu() {
System.out.println("欢迎管理员"+this.name+"登录");
System.out.println("1.查找图书");
System.out.println("2.新增图书");
System.out.println("3.删除图书");
System.out.println("4.显示图书");
System.out.println("0.退出系统");
Scanner sc = new Scanner(System.in);
int choice = sc.nextInt();
return choice;
}
}
package user;
import operation.*;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description: 普通用户 有四个操作:查找图书 借阅图书 归还图书 退出系统
* @Date: 2023/7/27 12:10
*/
public class NormalUser extends User{
public NormalUser(String name) {
super(name);
this.ioPerations = new IOperation[] {
new ExitOperation(),
new FindOperation(),
new BorrowOperation(),
new ReturnOperation(),
};
}
/**
* 普通用户菜单 1.查找图书 2.借阅图书 3.归还图书 0.退出系统
* @return 返回用户输入的选项,供主程序调用
*/
@Override
public int menu() {
System.out.println("欢迎"+this.name+"登录");
System.out.println("1.查找图书");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("0.退出系统");
Scanner sc = new Scanner(System.in);
int choice = sc.nextInt();
return choice;
}
}
import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description:
* @Date: 2023/7/27 12:11
*/
public class Main {
public static User login(){
System.out.println("请输入你的姓名:");
Scanner sc = new Scanner(System.in);
String name = sc.next();
System.out.println("请输入你的身份:1.管理员 2.普通用户");
int choice = sc.nextInt();
if(choice == 1) {
return new AdminUser(name);
}else {
return new NormalUser(name);
}
}
public static void main(String[] args) {
BookList bookList = new BookList();
User user = login();
while(true) {
int choice = user.menu();
user.doOperation(choice,bookList);
}
}
}
package operation;
import book.BookList;
/**
* @Author: Fourteen-Y
* @Description: 新增图书
* @Date: 2023/7/27 12:09
*/
public interface IOperation {
// 由于接口中的方法都是抽象方法,所以可以省略public abstract
void work(BookList bookList);
}
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description:
* @Date: 2023/7/27 12:07
*/
public class AddOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("新增图书!");
System.out.println("请输入图书的名字:");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
System.out.println("请输入图书的作者");
String author = sc.nextLine();
System.out.println("请输入图书的类型");
String type = sc.nextLine();
System.out.println("请输入图书的价格");
int price = sc.nextInt();
// 创建一个Book对象
Book book = new Book(name,author,price,type);
// 当BookList满了的时候,自动扩容成原来的2倍
BookList.ensureCapacity(bookList);
int currentSize = bookList.getUsedSize();
BookList.setBooks(currentSize,book);
// 更新usedSize
bookList.setUsedSize(currentSize + 1);
System.out.println("新增成功!");
}
}
上面用了一个确保容量的函数,自动扩容的函数,我们在BookList类里面加上这个函数
public static void ensureCapacity(BookList bookList) { // 如果当前数组已经满了,就扩容成原来的2倍 if (bookList.getUsedSize() == books.length) { Book[] newBooks = new Book[2 * books.length]; for (int i = 0; i < books.length; i++) { newBooks[i] = books[i]; } books = newBooks; } }
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description:
* @Date: 2023/7/27 12:08
*/
public class BorrowOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("借阅图书!");
System.out.println("请输入你要借阅图书的名字:");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
// 1.查找书籍是否存在
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
Book book = bookList.getPos(i);
if (book.getName().equals(name)) {
// 2.判断书籍是否被借出
if (book.isBorrowed()) {
System.out.println("这本书已经被借出去了!");
return;
}
// 3.借阅书籍
book.setBorrowed(true);
System.out.println("借阅成功!");
return;
}
}
System.out.println("没有你要借阅的图书");
}
}
package operation;
import book.Book;
import book.BookList;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description: 删除图书
* @Date: 2023/7/27 12:08
*/
public class DelOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("删除图书!");
System.out.println("请输入你要删除图书的名字:");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
// 1.查找书籍是否存在
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
Book book = bookList.getPos(i);
if (book.getName().equals(name)) {
// 2.删除书籍
for (int j = i; j < currentSize - 1; j++) {
Book book1 = bookList.getPos(j + 1);
BookList.setBooks(j,book1);
}
bookList.setUsedSize(currentSize - 1);
System.out.println("删除成功!");
return;
}
}
System.out.println("没有你要删除的书!");
}
}
package operation;
import book.Book;
import book.BookList;
/**
* @Author: Fourteen-Y
* @Description: 展示图书
* @Date: 2023/7/27 12:08
*/
public class DisplayOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("展示图书!");
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
Book book = bookList.getPos(i);
System.out.println(book);
}
}
}
package operation;
import book.BookList;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description: 查找图书
* @Date: 2023/7/27 12:09
*/
public class FindOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("查找图书!");
System.out.println("请输入你要查找图书的名字:");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
if (bookList.getPos(i).getName().equals(name)) {
System.out.println("找到这本书了,信息如下");
System.out.println(bookList.getPos(i));
return;
}
}
System.out.println("没有这本书!");
}
}
package operation;
import book.BookList;
import java.util.Scanner;
/**
* @Author: Fourteen-Y
* @Description: 归还图书
* @Date: 2023/7/27 12:09
*/
public class ReturnOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("归还图书!");
System.out.println("请输入你要归还图书的名字:");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
if (bookList.getPos(i).getName().equals(name)) {
if (bookList.getPos(i).isBorrowed()) {
bookList.getPos(i).setBorrowed(false);
System.out.println("归还成功!");
return;
}
System.out.println("这本书没有被借出去!");
return;
}
}
System.out.println("这本书不是该图书馆的书!");
}
}
package operation;
import book.BookList;
/**
* @Author: Fourteen-Y
* @Description: 退出系统
* @Date: 2023/7/27 12:08
*/
public class ExitOperation implements IOperation{
@Override
public void work(BookList bookList) {
System.out.println("退出系统!");
int currentSize = bookList.getUsedSize();
for (int i = 0; i < currentSize; i++) {
BookList.setBooks(i,null);
}
System.exit(0);
}
}
在上面的例子中,我们使用了封装来隐藏Book类的内部实现细节。图书的属性(书名、作者、价格、类型、是否被借出)都被声明为私有(private),这意味着它们不能直接从外部访问。我们为每一个属性都提供了公共的(getter/setter)方法来让外部代码访问这些属性的值。
get是得到属性的值,set是设置属性的值
我们的管理员和普通用户都有一些共性:都有名字,都会生产一个可以选择操作的菜单,两者的行为其实是一样的,只是可以操作的选项不同。所以我们在User类中把这些全定义好,通过管理员和普通用户来继承实现这些功能。
在系统中,我们选择不同的用户类型会出现不同的功能菜单。是因为我们对menu这个方法进行了重写,不同的对象调用这个方法会执行自己重写了的逻辑和功能。
通过使用多态,我们可以使用相同的方法处理不同类型的对象,这样代码更加灵活和可复用。
在上面的例子中,我们已经看到了Java中的抽象类的使用。在这个示例中,User类被声明为抽象类,它是一种抽象的概念,它表示用户的通用属性。
在上面的示例中,我们把所有的操作定义成了一个接口,我们定义IOperation接口就是进行所有的功能操作,然后通过不同的类来分别实现各自的功能。通过这个接口我们可以控制所有的功能。
这个简单的图书管理系统演示了Java面向对象编程的各个概念的应用。实际的项目中,面向对象编程将更复杂和丰富,但这个示例可以帮助你理解如何在实际项目中应用面向对象编程的概念。