我们学习JAVA之后,对面向对象会有朦朦胧胧的感觉,总感觉那么近又那么远,那么清晰又那么模糊,这里我带来一个图书小练习,里面整合了大部分面向对象相关的思想,希望能帮到你

注意:这里只是为了让我们理解面向对象,逻辑不妥当,可以自行修改

目录

1.运行展示

2.代码讲解

2.1书类【包含封装】

2.2书架类【包含封装】

2.3操作接口(IOperation)【包含接口,多态】

2.4新增图书

2.5借出操作

2.6删除操作【包含封装】

2.7显示图书

2.8退出系统

2.9查找图书

2.10归还图书

2.11不同用户的操作【包含继承】

2.11.1使用者类(父类)

2.11.2管理员类(子类)

2.11.3用户身份(子类)

2.12main函数整合(重点)

3.总结


1.运行展示

javasscript面向对象 java面向对象实战_开发语言

 

javasscript面向对象 java面向对象实战_开发语言_02

这里给了两种身份,我们可以用两种身份登陆,从而获取不同的操作权限,在操作的内部给一个目录,然后依次实现里面的相关逻辑就好,我们的重点是面向对象的框架搭建

2.代码讲解

这里是我建的相关包,可以参考

javasscript面向对象 java面向对象实战_javasscript面向对象_03

2.1书类【包含封装】

既然是图书系统,所以肯定首先有书籍类

package Book;

public class Book {
    private String name;        // 图书名
    private String author;      // 图书作者
    private float 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 float getPrice() {
        return price;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public boolean getBorrowed() {
        return isBorrowed;
    }

    public void setBorrowed(boolean isBorrowed) {
        this.isBorrowed = isBorrowed;
    }

    public Book(String name, String author, int price, String type) {
        this.name = name;
        this.author = author;
        this.price = price;
        this.type = type;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price + " " +
                (!isBorrowed ? "未借出" : "已借出")
                ;
    }
}

在这个类中,我们只需要提供对应的get,set方法和构造方法,还有toString方法即可,主要用来操作图书,这里体现了我们面向对象的封装,都是基础性的东西,没啥能提的点

2.2书架类【包含封装】

既然是图书管理系统,那么肯定会有一个书架来将图书进行整合操作的,那我们就建一个BookList类,在这里面书写对应的代码

package Book;


public class BookList {
    private Book[] books = new Book[10];
    private int  usedSize;
    public BookList(){
        books[0] = new Book("三国演义"," 罗贯中 ", 19 , "小说");
        books[1]= new Book("红楼梦"," 曹雪芹 ", 39 , "小说");
        books[2] = new Book("西游记"," 吴承恩", 29 , "小说");
        usedSize = 3;
    }
    /*
    寻找pos位置的书
     */
    public Book getBook(int pos){
        return books[pos];
    }
    /*
    设置pos位置的书
     */
    public void setBook(int pos,Book book){
        books[pos] = book;
    }
    /*
    获取当前书本的个数
     */
    public int getUsedSize(){
        return usedSize;
    }
    /*
    修改当前书的个数
     */
    public void setUsedSize(int size){
        usedSize = size;
    }

}

这里既然是书架,我们就可以创建一个数组,来存储书籍,其次,我们需要知道总共有几本书,所以设置一个usedSize来记录图书的个数,并且提供set和get操作的方法,然后我们在前三个数组中提前存3本书,然后也提供对应的get和set方法,这里要注意get和set方法中的pos都是books数组的下标

2.3操作接口(IOperation)【包含接口,多态】

在这里,我们对需要进行的操作实现一个接口,然后定义一个work方法,这样我们就可以在不同的操作类中调用work方法,来实现多态了

package operation;

import Book.BookList;


public interface IOperation {
    void work(BookList bookList);

}

我们只要在操作类中实现这个接口,就可以调用同一个方法,然后得到不同的结果了,体现了多态的思想

2.4新增图书

这部分就是简单的逻辑操作直接看代码

import Book.BookList;

import java.util.Scanner;


public class AddOperation implements IOperation{
    public void work(BookList bookList){
        Scanner sc = new Scanner(System.in);
        System.out.println("新增图书");
        System.out.println("请输入图书的名字");
        String name = sc.nextLine();
        System.out.println("请输入图书的作者");
        String author = sc.nextLine();
        System.out.println("请输入图书的价格");
        int price = sc.nextInt();
        System.out.println("请输入图书的类型");
        String type = sc.nextLine();
        Book book = new Book(name,author,price,type);
        int currentSize = bookList.getUsedSize();
        bookList.setBook(currentSize,book);
        bookList.setUsedSize(currentSize+1);
        System.out.println("新增完成");
    }
}

2.5借出操作

这里的借出操作,我们只需要进行寻找对应的操作,然后再对isBorrow进行修改就可以了

import Book.BookList;

import java.util.Scanner;

public class BorrowOperation implements IOperation{
    public void work(BookList bookList){
        Scanner sc = new Scanner(System.in);
        System.out.println("借阅图书");
        System.out.println("请输入你需要借阅的图书");
        String name = sc.nextLine();
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            Book book = bookList.getBook(i);
            if(book.getName().equals(name)){
                book.setBorrowed(true);
                System.out.println("借阅成功");
            }
        }
        System.out.println("没找到这本书");
    }
}

2.6删除操作【包含封装】

删除操作只需要我们把图书后面的图书往前进行覆盖,然后对书架长度进行修改即可

package operation;

import Book.Book;
import Book.BookList;

import java.util.Scanner;


public class DelOperation implements IOperation {
    public void work(BookList bookList) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入需要删除的书名");
        String key = sc.nextLine();
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            Book book = bookList.getBook(i);
            if (book.getName().equals(key)) {
                for (int j = i; j < bookList.getUsedSize() -1; j++) {
                    bookList.setBook(j,bookList.getBook(j+1)) ;
                }
                bookList.setUsedSize(bookList.getUsedSize()-1);
                System.out.println("删除成功");
                return;
            }
        }
        System.out.println("未找到这本书");
    }
}

注意:这里的覆盖操作必须用setBook和getBook来进行操作,因为我们的Book是被我们用privet进行修饰的,所以我们是不能直接进行操作的,所以要主get和set方法,包括我们的书架长度,依然是用get和set方法来操作的,又体现了我们的封装性。

2.7显示图书

就是遍历打印

package operation;

import Book.Book;
import Book.BookList;


public class DisplayOperation implements IOperation{
    public void work(BookList bookList){
        System.out.println("显示图书");
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            Book book = bookList.getBook(i);
            System.out.println(book);
        }
    }
}

这里其实也体现了多态,因为我们Book的toString被重写了,所以我们打印的时候就发生了动态绑定,调用的是我们重写的toString方法

2.8退出系统

这个涉及到内存的清理,我们这里暂时不讲,所以暂时用简单的代码进行叙述即可

package operation;

import Book.BookList;


public class ExitOperation implements IOperation{
    public void work(BookList bookList){
        System.out.println("退出系统");
    }
}

2.9查找图书

这个其实我们在删除图书中已经使用过了,同样的逻辑

package operation;

import Book.Book;
import Book.BookList;

import java.util.Scanner;


public class FindOperation implements IOperation{
    public void work(BookList bookList){
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入查找的图书名");
        String name = sc.nextLine();
        int currentSize = bookList.getUsedSize();
        for (int i = 0; i < currentSize; i++) {
            Book book = bookList.getBook(i);
            if(book.getName().equals(name)){
                System.out.println("找到了");
                System.out.println(book);
                return;
            }
        }
        System.out.println("没有这本书");

    }
}

2.10归还图书

这里我们只需要把对应的图书isBorrow更改为未借出即可

package operation;

import Book.Book;
import Book.BookList;

import java.util.Scanner;


public class ReturnOperation implements IOperation{
    public void work(BookList bookList){
        Scanner sc = new Scanner(System.in);
        System.out.println("归还图书");
        System.out.println("请输入你需要归还的图书");
        String name = sc.nextLine();
        for (int i = 0; i < bookList.getUsedSize(); i++) {
            Book book = bookList.getBook(i);
            if(book.getName().equals(name)){
                book.setBorrowed(false);
                System.out.println("归还成功");
            }
        }
        System.out.println("没找到这本书");
    }
}

2.11不同用户的操作【包含继承】

2.11.1使用者类(父类)

这里我们因为不同的用户进行操作,但是都是人,都有个名字,所以我们书写一个父类用来继承

package User;

import Book.BookList;
import operation.IOperation;


public abstract class User {
    protected String name;
    protected IOperation[] iOperations;
    public User(String name){
        this.name = name;
    }
    public abstract int menu();
    public  void doOperation(int choice, BookList bookList){
        this.iOperations[choice].work(bookList);            
    }

}

这里我们定义了一个IOperation(接口)类型的数组,但是我们并没有给他初始化,这个是为了我们在对于不同的操作者身份进行访问的时候,可以根据对应的选择操作调用到不同的操作类方法中去,这也是整个代码的较为核心的部分

然后我们给不同用户看到的目录是不同的,所以我们让这个menu方法被定义为抽象类,让我们在子类中对齐进行重写操作,这里的返回值类型是int,可以用来接收用户的选择

doOperation我们在main方法中讲,这里讲的话不好讲

2.11.2管理员类(子类)

这里我们因为有不同的用户,所以定义了不同身份的类,继承使用者类,然后对我们选择的身份进行对应的操作

package User;

import operation.*;

import java.util.Scanner;


public class AdminUser extends User{
    public AdminUser(String name){
        super(name);
        this.iOperations = new IOperation[]{
                new ExitOperation(),
                new FindOperation(),
                new AddOperation(),
                new DelOperation(),
                new DisplayOperation()
        };
    }
    public int menu(){
        System.out.println("1.查找图书");
        System.out.println("2.新增图书");
        System.out.println("3.删除图书");
        System.out.println("4.显示图书");
        System.out.println("0.退出系统");
        System.out.println("请选择:>");
        Scanner sc = new Scanner(System.in);
        return sc.nextInt();
    }
}

这里我们有个重点:对从父类继承过来的iOperation进行初始化,分配内存操作,这里我用一个图,可以更好的理解

javasscript面向对象 java面向对象实战_开发语言_04

 这里相当于我们iOperation数组中存了五个对象(可以认为是地址),然后由于他们都实现了IOperation接口,所以都发生了向上转型,为我们后面的调用奠定了基础

2.11.3用户身份(子类)

这里和上面的基本一致,只是我们的menu打印不同的东西和上面的对象使用对应的操作即可

package User;

import operation.*;

import java.util.Scanner;

public class NormalUser extends User{
    public NormalUser(String name){
        super(name);
        this.iOperations = new IOperation[]{
                new ExitOperation(),
                new FindOperation(),
                new BorrowOperation(),
                new ReturnOperation()
        };
    }
    public int menu() {
        System.out.println("1.查找图书");
        System.out.println("2.借阅图书");
        System.out.println("3.归还图书");
        System.out.println("0.退出系统");
        System.out.println("请选择:>");
        Scanner sc = new Scanner(System.in);
        return sc.nextInt();
    }
}

2.12main函数整合(重点)

这里到我们的最重要的地方,整合先看代码

import Book.BookList;
import User.*;

import java.util.Scanner;


public class Main {
    public static User login() {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你的姓名");
        String name = sc.nextLine();
        System.out.println("请选择你的身份 1.管理员  0.普通用户");
        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);
            if (choice == 0) {
                break;
            }
        }
    }
}

首先可以看到有一个Login方法,这个是登入操作,我们返回值用父类的类型User来进行接收,这里就发生了向上转型

其次我们看main函数里面,首先执行Login,选择登入的身份,然后用while进行循环操作,用chioce接收menu的返回值,如果是0,则结束循环

最后,我们可以看到我们用user调用了doOperation方法,这里我们因为发生了动态绑定,所以我们的user调用就和我们选择的身份进行调用时一个效果,也体现了多态,

然后我们分析doOperation方法

首先是参数,因为要对书架进行对应的操作,所以我们把书架和我们刚刚目录中选择的choice作为形参传进去,在看doOperation方法

javasscript面向对象 java面向对象实战_java_05

 我们首先用this也就是上面的user,对他的iOperation数组中的第chioce个元素进行操作,进行这个元素(也就是上面new的对象)我们可以实现里面的操作,我们都知道所有的操作类中,都有一个work方法,所以我们可以调用其中得到work方法,从而完成我们选择的操作

3.总结

这个小练习融合了几乎所有面向对象思想

对上面代码整合到编译器即可运行,如有不妥当得到地方,还请大佬指点