整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理

Posted 一枚小比特

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理相关的知识,希望对你有一定的参考价值。

整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理

重要逻辑

  • 找对象

    1. 书有名字、作者、类型、价格、是都被借阅的状态。可以作为一类对象
    2. 用户可以有姓名等,可以成为一个对象,在此处,用户又可细化为两类(管理员和普通用户),他们都可以独成一类
    3. 对图书的增删查改这些行为可以作为对象,作为一类
  • 创建对象

    1. 书有了,整合这些数据的数据结构在此处选择较为简单的顺序表作为手段。后续学完数据库,可以将数据放在数据库中。
    2. 为了面向对象编程,我们将行为各成一派,所有派别都实现一个接口(所有派的掌门人),这里既可以认为是实现接口,也可以理解成继承关系,为后续动态绑定做铺垫。
    3. 针对用户方面,我们希望的是:一个用户选择身份后,其背后的逻辑(比如对应身份的菜单(用一个数组实现))已经初始化完成,再让用户进行下一步选择时,已经可以进入功能(方法)的使用了。
  • 使用对象

    前述对象的交互,完成逻辑表达。


第一步:我们可以先针对书,建立一个包,该包下建立类和顺序表,之前都是写在一个包里,现在是写在一个包下的两个类中,这也是真正的习惯之一。(注意事项已经写在代码注释行)💛

package book;

public class Book 
    private String name;
    private String author;
    private String type;
    private int price;
    private boolean isBorrowed;
    //构造方法

    public Book(String name, String author, String type, int price) 
        this.name = name;
        this.author = author;
        this.type = type;
        this.price = price;
    //isBorrowed默认为false,false表未借出

    //为了打印出各个书,对toString进行重写

    @Override
    public String toString() 
        return "Book" +
                "name='" + name + '\\'' +
                ", author='" + author + '\\'' +
                ", type='" + type + '\\'' +
                ", price=" + price +
                (isBorrowed==true?" 已被借出 ":" 未被借出 ")+
                '';
    
    //对书的各个私有成员提供接口
    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;
    

    public boolean isBorrowed() 
        return isBorrowed;
    

    public void setBorrowed(boolean borrowed) 
        isBorrowed = borrowed;
    

对BookList来说

package book;

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lebronHArden
 * Date: 2021-12-08
 * Time: 9:01
 */
public class BookList 
    private Book[] books=new Book[10];
    private int usedSize;

    public BookList() 
        books[0]=new Book("三国演义","罗贯中","小说",17);
        books[1]=new Book("水浒传","施耐庵","小说",44);
        books[2]=new Book("西游记","吴承恩","小说",35);
        this.usedSize=3;//不写这个,那后续打印数组时,这个数字默认就是0,那啥也打印不出
    

    //获取“书顺序表的书的数量”
    public int getUsedSize() 
        return usedSize;
    

    //设置书的数量
    public void setUsedSize(int usedSize) 
        this.usedSize = usedSize;
    

    //获取到pos位置处的书Book
    public Book getPos(int pos)
        if(pos<0||pos>this.usedSize)//this是否合理
            System.out.println("下标不合法");
            return null;
        
        return books[pos];
    
    //给pos位置插入一本书
    public boolean isFull()
        return this.usedSize==this.books.length;
    
    public void setPos(int pos,Book book)
        if(isFull())
            this.books= Arrays.copyOf(this.books,2*this.books.length);//扩容两倍
        
        if(pos<0||pos>this.usedSize)
            System.out.println("下标不合法");
            return;
        
        for (int i = this.usedSize-1; i >=pos ; i++) 
            this.books[i+1]=this.books[i];
        
        this.books[pos]=book;
        this.usedSize++;
    


第二步:针对用户:⌚️

目前用户的抽象我们只能想到只要是用户都用名字,那就先写出来,继承关系也打好。

第三步:针对我们的Main函数:其逻辑

  1. 先建立书的顺序表

  2. 让用户登录,这里很重要,逻辑是:让用户选择好身份后,我们的编译器已经生成对应其身份的菜单了!并且呢,不管用户选哪个身份,我们都用User去接受,使其发生向上转型,为什么让它向上转型?因为要实现多态!哪里多态?我们可以用父类引用打印不同子类的菜单!哦!所以这里User和其子类中都要写menu(),并使其构成重写,不过打印出来的菜单只是给我们看的,其实在打印之前,也就是让用户选择身份的时候,再说白了,就是通过子类实例化对象的时候,这个对应菜单的数组就已经建立好了。

  3. 让用户根据其身份选择功能,也就是说我们给用户一个menu,他们能看到一些功能,他们做出选择后(其实就是返回值),我们的编译器就能拿到对应的方法进行下一步的执行。

    针对Main:

import book.BookList;
import user.AdminUser;
import user.NormalUser;
import user.User;

import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lebronHArden
 * Date: 2021-12-08
 * Time: 9:33
 */
public class Main 
    public static User login()
        Scanner scanner=new Scanner(System.in);
        System.out.println("请输入姓名:");
        String name=scanner.nextLine();
        System.out.println("========请选择访问身份:1:管理员      0:普通用户========");
        int choice=scanner.nextInt();
        while(true)
            if(choice==1)
                return new AdminUser(name);
            else if(choice==0)
                return new NormalUser(name);
            else
                System.out.println("输入错误,请重新输入:");
            
        
    
    public static void main(String[] args) 
        BookList bookList=new BookList();//建一个书的顺序表
        User user=login();//向上转型

        while(true)

            int choice=user.menu();//多态式打印各自的菜单

            user.doWork(choice,bookList);
        


    


当然我们的main函数编到子类用户实例化的时候要去对子类用户和用户做思考:

  1. 子类和父类都要menu(),并且多态式打印

  2. 子类用户实例化的时候,要产生对应的菜单(数组),反正两类子类用户都有对应的数组,那再在父类用户User中添一个字段(操作的那个引用),这个引用也将在子类构造方法中先于子类自身构造时先被初始化,到这用户这块基本都齐全了。先思考到这。然后代码给你们看看:

    User:

package user;

import book.BookList;
import operation.IOperation;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lebronHArden
 * Date: 2021-12-08
 * Time: 9:23
 */
public abstract class User 
    protected String name;
    protected IOperation[] iOperations;

    public abstract int menu();

    public void doWork(int choice, BookList bookList)
        iOperations[choice].work(bookList);
    



AdminUser:

package user;

import operation.*;

import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lebronHArden
 * Date: 2021-12-08
 * Time: 9:23
 */
public class AdminUser extends User
    public AdminUser(String name)
        this.name=name;
        this.iOperations=new IOperation[]
                new ExitOperation(),
                new FindOperation(),
                new AddOperation(),
                new DelOperation(),
                new DisplayOperation()
        ;
    
    public int menu()
        System.out.println("========管理员菜单========");
        System.out.println("Hello "+this.name+" 欢迎来到图书小练习");
        System.out.println("0:退出系统");
        System.out.println("1:查找图书");
        System.out.println("2:新增图书");
        System.out.println("3:删除图书");
        System.out.println("4:打印图书");
        System.out.println("请输入你的选择:");
        Scanner scanner=new Scanner(System.in);
        int choice =scanner.nextInt();
        return choice;
    

NormalUser:

package user;

import operation.*;

import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lebronHArden
 * Date: 2021-12-08
 * Time: 9:23
 */
public class NormalUser extends User
    public NormalUser(String name)
        this.name=name;//这个是对从父类继承过来的成员进行初始化
        this.iOperations=new IOperation[]//这里我的理解也都是向上转型
                new ExitOperation(),
                new FindOperation(),
                new BorrowOperation(),
                new ReturnOperation()
        ;
    
    public int menu()
        System.out.println("========普通用户菜单========");
        System.out.println("Hello "+this.name+" 欢迎来到图书小练习");
        System.out.println("0:退出系统");
        System.out.println("1:查找图书");
        System.out.println("2:借阅图书");
        System.out.println("3:归还图书");
        System.out.println("请输入你的选择:");
        Scanner scanner=new Scanner(System.in);
        int choice =scanner.nextInt();
        return choice;
    



第三步:Main函数已经完成了2/3了,🌮

这里还是想通过父类引用实现多态的调用方法,那就继续在User和子类用户里新添一个方法(要构成重写):doWork()

这个方法,要能根据选择拿到数组的元素,这个数组元素你们发现了没有,每个元素都是接口,那之前说了所有的方法都实现了这个接口,就相当于继承,

这里通过IO接口又一次实现多态!

上代码:IOperation:

package operation;

import book.BookList;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lebronHArden
 * Date: 2021-12-08
 * Time: 9:31
 */
public interface IOperation 
    void work(BookList bookList);


功能函数:

如AddOperation:

package operation;

import book.Book;
import book.BookList;

import java.util.Scanner;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lebronHArden
 * Date: 2021-12-08
 * Time: 9:25
 */
public class AddOperation implements IOperation
    public void work(BookList bookList)

        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("请输入书的类型:");
        String type=scanner.nextLine();//书类
        System.out.println("请输入书的价格:");
        int price=scanner.nextInt();//价格

        Book book=new Book(name,author,type,price);
        int curSize=bookList.getUsedSize();

        bookList.setPos(curSize,book);

        bookList.setUsedSize(curSize+1);
        System.out.println("填加图书成功");
        System.out.println("===========================");
    


其余的留给读者去实现。下篇博客给大家揭晓本人的答案(当然不一定最好)⏰

以上是关于整合 多态+数据结构(顺序表)+类+封装+接口+继承的面向对象编程的一个实用案例之:图书馆管理的主要内容,如果未能解决你的问题,请参考以下文章

Java编程思想8.多态

[读书笔记]Java编程思想第8章之多态

java多态

面向对象:封装继承和多态接口

009.面向对象之多态封装密封类接口

关于多态的学习