【项目】简单的图书管理系统(上)

目录

目录

▮设定对象的类

▮类设计

▪ Book - 书类

▪ Bookcase - 书架

▪ User - 用户(父类)

• AdminiUser - 管理员

▪ NomalUser - 普通人

▮接口和行为类

▪接口 - Iopreration

▪退出系统 - ExitOperation (exit:v,退出)

▪添加书籍 - AddOperation  (add:v,添加)

▪借阅书籍 - BorrowOperation  (borrow:v,借阅)

▪展示书籍 - DisOperation  (display:v,展示,陈列)

▪归还书籍 - ReturnOperation  (return:v,返回)

▪查找书籍 - FindOperation  (find:v,找出)

▪删除书籍 - DelOperation  (delete:v,删除)

▮主函数main来启动项目

▪Main类 

▪管理员的菜单

▪普通人菜单


        欢迎各位在评论区提问或指出问题,请多多赐教   ——海鱼🐟

完整代码:http://t.csdn.cn/yQKww

▮设定对象的类

        首先,图书管理系统最基本的东西就是书,“书”这个类是整个系统的基础,所以我们先创造出“书”。接着,有了书以后,要有一个放书的容器,我们需要创建一个“书架”,用这个类来装书。最后,有书有书架后,就要有人来使用它们,我们要创建一个“用户”来使用它们,根据用户的身份不同,我们给予用户不同的操作权限,即“普通人”与“管理员”的权限不同。

         java是面向对象的语言。在进行编程前,要先给项目中的对象设计好类。图书管理系统所设计的类如上。注意:用户是普通人和管理员的父类。


▮类设计

▪ Book - 书类

        对于一本书,它有着“书名,作者,种类,价格,等属性”。当我们拿起一本书阅读时,总是会先去看看书的封面,此时书的封面上写着书名,书通过这种方法告诉了“用户”,它的名字是什么?所以,现实中我们都知道,要了解书名是什么,就要去看书的封面。但在java里,“书”通过getName这个公开的方法来告诉我们书名是什么,所以,“用户”想要知道了解书名,只能通过getName()来了解,想要修改书名,只能通过setName()来修改。

        书的其他属性同上。

        •代码演示

public class Book {
   private String name; //书名
   private String author; //作者
   private int price; //价格
   private String type; //种类
   private boolean isBorrowing; //借阅状态

    //构造方法
    public Book(String name, String author, int price, String type) {
        this.name = name;
        this.author = author;
        this.price = price;
        this.type = type;
    }
    
    //toString输出成员属性
    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", type='" + type + '\'' +
                ", Borrow='"+ (isBorrowing ?"已被借阅" :"未被借阅") + '\'' + //IDEA的快捷方式不会自动生成此条,需要自行添加
                '}';
    }
}

        这里省略了get,set成员属性的方法,记得自己生成,因为成员属性都是private所修饰,进行了封装,不添加的话没法操作成员属性。

        toString()进行了修改,不是全靠自动生成。里面还使用了三木操作符“ …?… :… ”操作,代码中有标注。

▪ Bookcase - 书架

        对于一个书架,它首先要有“容量”,即书架上能放几本书?然后,我们要在书架里掏出框框,作为放书的地方,即“Book[ ] booklist”。最后,把书放到书架后,我们还要知道,书架上放有几本书,即“书本个数”

        有了书架后,我们要放书或换书,即setBooks;我们还要通过书架的索引来取书,即getBooks()。我们每次操作书籍后,我们要知道书架上还有几本书,即getUsednumber();我们还有可能改变书本个数,即setUsednumber()。

         •代码演示

public class Bookcase {
    private static final int BOOKCASE_SIZE = 10; //书架容量,用final修饰,不可修改
    private Book[] booklist = new Book[BOOKCASE_SIZE]; //书单
    private int usednumber; //使用书架的书本数量,即书架上有几本书

    //默认构造方法
    public Bookcase() {
        //书架上的的默认放置的书本
        booklist[0] = new Book("三国演义", "罗贯中", 19, "小说");
        booklist[1] = new Book("西游记", "吴承恩", 28, "小说");
        booklist[2] = new Book("红楼梦", "曹雪芹", 39, "小说");
        this.usednumber = 3;
    }

    //功能:根据下标来找到书籍
    public Book getBooks(int pos) { //参数:下标
        return booklist[pos]; //返回:下标对应的Book
    }
    //功能:更换下标处的书籍
    public void setBooks(int pos, Book book) { //参数:下标,新的Book对象
        booklist[pos] = book;
    }
    //功能:得到书架上书本的个数
    public int getUsednumber() {
        return usednumber;
    }
    //功能:修改书架上书本的个数
    public void setUsednumber(int usednumber) {
        this.usednumber = usednumber;
    }
}

        这里提上一句。很多时候,我很难设计好对象所要进行的行为。当我不知道该写什么方法的时候,我都会选择去写后面的代码,写着写着就会发现,欸,这里需要的方法我没有写,然后跑回来补上所需的方法。就这样,我一直来来回回的写着,最后写出了我的项目。

写完后在回头优化一下自己的代码,删减和调整一下,就完成了一个非常不错的项目。

        所以说,大家都不要害怕写项目,不知道怎么写代码的时候,就先去写后面的代码。一直写下去,通过后面的代码来提醒你,你要写什么样的代码。

▪ User - 用户(父类)

        对于一个用户,我们要知道它的“名字”和“身份”。同时要能获取用户的名字,即getName()。有了用户后,要根据他们的身份赋予他们不同的行为,这里用的是接口数组“Ioperation[] ioperation”来记录他们的行为。
        用户的身份不需要作为属性,因为要用“向上转型”来绑定子类,绑定不同的子类,就代表着不同的身份。

        •代码演示

public class User  {
    private String name; //用户名
    //构造方法,非默认
     public User(String name){
        this.name = name;
    }
     //这是一个接口数组,装的是用户能进行的行为
    public Ioperation[] ioperation; 
    //这个方法会被子类所重写,用于打印菜单,得到选项
    public int menu (){ //menu:n,菜单
        return 0;
     }
     //输出用户名
     public String gteName(){
         return this.name;
     }
}

        operation是一个接口数组用来装入各种行为,至于要装入什么行为,由子类来定。而且子类要进行的行为都要通过它来调用,所以它用“ public ”来修饰,没有封装。

        menu()这个方法后文会讲,现在不管。

• AdminiUser - 管理员

        管理员的权限是固定的,能进行的行为也是固定的。所以在构造方法里就给“管理员”赋予行为,因为构造方法只调用一次。  

         •代码演示

public class AdminiUser extends User{
    //构造方法,非默认
    public AdminiUser(String name){
        super(name); //调用父类构造方法
        operation = new Ioperation[]{ //创建了一个数组,里面装着各种对象
                new ExitOperation(), //实现“退出系统”方法的类
                new AddOperation(),  //实现“增加书籍”
                new DelOperation(),  //实现“删除书籍”
                new DisOperation(),  //实现“展示书籍”
        };
    }
}

        这个对象所要进行的行为没有写进这个类中,而是使用“接口”来连接对象要进行的行为。至于这些行为怎么实现,后文慢慢介绍。

▪ NomalUser - 普通人

        普通人的权限是固定的,能进行的行为也是固定的。所以在构造方法里就给“普通人”赋予行为,因为构造方法只调用一次。

        •代码演示

public class NomalUser extends User{ //继承了父类User
    //构造方法,非默认
    public NomalUser(String name){
        super(name); //调用父类构造方法
        super.operation = new Ioperation[]{
           new ExitOperation(),  //实现“退出系统”
           new BorrowOperation(),//实现“借阅书籍”
           new ReturnOperation(),//实现“归还书籍”
           new FindOperation(),  //实现“查找书籍”
        };
    }
}

        这个对象所要进行的行为没有写进这个类中,而是使用“接口”来连接对象要进行的行为。至于这些行为怎么实现,后文慢慢介绍。


▮接口和行为类

▪接口 - Iopreration

         接口里的抽象方法代表着一类行为,别的类通过实现接口,重写接口的抽象方法来与接口相绑定。当接口这个USB插到左边的某个类时,通过使用这个USB就能调用,被插入的类里的,重写了接口抽象方法的,用户所需要的行为方法。
        被插入:Ioperation operation = new 被插入类();

        •接口代码展示

public interface Ioperation { //operation:n. 操作
    //功能:这是一个抽象方法,它的功能由七大类来重写实现
    void work(Bookcase bookcase); // 参数:Bookcase的一个实例对象,无返回
}

        接口左边有七个类,这七个类都实现了接口Ioperation,里面都只有一个重写方法,每个重写的方法的参数和返回值类型是一样的,与接口的抽象方法一致。唯独不同的就只有方法的功能。

▪退出系统 - ExitOperation (exit:v,退出)

public class ExitOperation implements Ioperation{ //这个类实现了接口
    @Override //重写的标志
    public void work(Bookcase bookcase) {
        System.out.println("退出系统");
        System.exit(0); //调用了System类中的exit方法,传入0表示程序正常结束
    }
}

        用类System的exit()方法来退出程序,给exit传入“0”表示程序正常退出。

▪添加书籍 - AddOperation  (add:v,添加)

public class AddOperation implements Ioperation{ //这个类实现了接口
    @Override
    public void work(Bookcase bookcase){ //传入一个Bookcase的对象
        System.out.println("-----添加书籍-----");
        //输入添加书籍的信息
        Scanner sc = new Scanner(System.in); 
        System.out.println("请输入书籍名称");
        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(); //这里是整形,上面的都是字符串

        //调用对象bookcase的方法得到书架上书籍的数量
        int usednumber = bookcase.getUsednumber(); 
        //调用对象bookcase的setBooks方法,new了一个新的书籍放进书架
        bookcase.setBooks(usednumber,new Book(name,author,price,type)); //因为数组下标是从0开始的,所以usednumber作为索引时,正好指向一个空位
        //添加了一本书籍后,书架上书籍的数量加1
        bookcase.setUsednumber(usednumber+1);
        System.out.println("添加成功");
    }
}

        此方法传入一个类型为Bookcase的对象:bookcase。首先,创建几个变量来接受输入的书籍属性;然后,取得bookcase的“书籍数量”作为下标索引,因为数组下标是从0开始的,所以书籍数量作为下标,正好指向书架上的空位;接着,new一个新的Book对象,用前面输入的变量来初始化后,传给方法bookcase.setBooks()来添加书籍;最后,用bookcase.setUendnumber()方法给“书籍数量”加1。

▪借阅书籍 - BorrowOperation  (borrow:v,借阅)

public class BorrowOperation implements Ioperation{ //这个类实现了接口
    @Override
    public void work(Bookcase bookcase) { //传入了一个类型为Bookcase的对象
        System.out.println("-----借阅书籍-----");
        //输入借阅书籍的名称
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入借阅书籍名称");
        String name = sc.nextLine();
        //调用对象bookcase的方法得到书架上书籍的数量,作为遍历结束的条件
        int usednumber = bookcase.getUsednumber();

        //遍历书架里所有的书籍
        for(int i=0; i<usednumber; i++){
            //在书架中寻找与借阅书籍名称相同的书籍
            if(name.equals(bookcase.getBooks(i).getName())){ 
                    //name.equals(str): 调用了字符串name的实例方法,来比较name是否与str同名
                    //bookcase.getBooks(i): 找到下标i对应的Book对象
                    //.getName(): 得到此Book对象的"书名"属性,这是一个字符串属性,即str
                System.out.println("借阅成功");
                //把这本书的属性改为“已借阅”
                Book book = bookcase.getBooks(i);
                book.setBorrowing(true);
                System.out.println(book);
                //若找到此书,则直接结束这个方法,不执行下方"未查到此书"的打印
                return;
            }
        }
        System.out.println("未查到此书");
    }
}

        此方法传入一个类型为Bookcase的对象:bookcase。首先,用一个变量“name”来接收借阅书名;然后,遍历bookcase的booklist(书单)[];接着,用字符串变量name的equals()来一一比对,bookcase.booklist[]里,书籍的书名;最后,找到同名书籍后,用setBorrowing()把此书的借阅状态改成“已借阅”

▪展示书籍 - DisOperation  (display:v,展示,陈列)

public class DisOperation implements Ioperation{ //这个类实现了接口
    @Override public void work(Bookcase bookcase) {
        System.out.println("-----展示书籍-----");
        //调用对象bookcase的方法得到书架上书籍的数量,作为遍历结束的条件
        int usednumber = bookcase.getUsednumber();
        for(int i=0; i<usednumber; i++){
            //使用println(对象)来打印对象的所有属性,
            System.out.println(bookcase.getBooks(i));
                //bookcase.getBooks(i): 找到下标i对应的Book对象
                //println(对象)等同于调用对象的toString()方法,所以对象内部要重写toString
        }
        //书架书籍为空的情况
        if(usednumber == 0){
            System.out.println("图书馆书籍为空");
            return;
        }
    }
}

        此方法传入一个类型为Bookcase的对象:bookcase。首先,遍历bookcase的booklist(书单)数组;然后,bookcase.getBooks(i)取得类Book的对象;最后,用println(Book对象)调用toString()来打印对象。

▪归还书籍 - ReturnOperation  (return:v,返回)

public class ReturnOperation implements Ioperation{ //这个类实现了接口
    @Override
    public void work(Bookcase bookcase) {
        System.out.println("-----归还书籍-----");
        //输入归还书籍的名称
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入归还书籍名称");
        String name = sc.nextLine();
        
        //调用对象bookcase的方法得到书架上书籍的数量,作为遍历结束的条件
        int usednumber = bookcase.getUsednumber();
        for(int i=0; i<usednumber; i++){
            //在书架中寻找与借阅书籍名称相同的书籍
            if(name.equals(bookcase.getBooks(i).getName())){ 
                    //name.equals(str): 调用了字符串name的实例方法,来比较name是否与str同名
                    //bookcase.getBooks(i): 找到下标i对应的Book对象
                    //.getName(): 得到此Book对象的"书名"属性,这是一个字符串属性,即str
                System.out.println("归还成功");
                //把这本书的属性改为“未借阅”
                Book book = bookcase.getBooks(i);
                book.setBorrowing(false);
                System.out.println(book);
                //若找到此书,则直接结束这个方法,不执行下方"图书馆未收藏此书"的打印
                return;
            }
        }
        System.out.println("图书馆未收藏此书");
    }
}

        此方法传入一个类型为Bookcase的对象:bookcase。首先,用一个变量“name”来接收归还书名;然后,遍历bookcase的booklist(书单)[];接着,用字符串变量name的equals()来一一比对,bookcase.booklist[]里,书籍的书名;最后,找到同名书籍后,用setBorrowing()把此书的借阅状态改成“未借阅”。

▪查找书籍 - FindOperation  (find:v,找出)

public class FindOperation implements Ioperation{ //这个类实现了接口
    @Override
    public void work(Bookcase bookcase) {
        System.out.println("-----查找书籍-----");
        //输入查找书籍的名称
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入查找书籍名称");
        String name = sc.nextLine();
        //调用对象bookcase的方法得到书架上书籍的数量,作为遍历结束的条件
        int usednumber = bookcase.getUsednumber();

        if(usednumber == 0){
            System.out.println("图书馆书籍为空");
            return;
        }

        for(int i=0; i<usednumber; i++){
            //在书架中寻找与借阅书籍名称相同的书籍
            if(name.equals(bookcase.getBooks(i).getName())){ 
                    //name.equals(str): 调用了字符串name的实例方法,来比较name是否与str同名
                    //bookcase.getBooks(i): 找到下标i对应的Book对象
                    //.getName(): 得到此Book对象的"书名"属性,这是一个字符串属性,即str
                System.out.println("查找成功");
               //使用println(对象)来打印对象的所有属性,
                System.out.println(bookcase.getBooks(i));
                    //bookcase.getBooks(i): 找到下标i对应的Book对象
                    //println(对象)等同于调用对象的toString()方法,所以对象内部要重写toString
                //若找到此书,则直接结束这个方法,不执行下方"未查到此书"的打印
                return;
            }
        }
        System.out.println("未查到此书");
    }
}

        此方法传入一个类型为Bookcase的对象:bookcase。首先,用一个变量“name”来接收查找书名;然后,遍历bookcase的booklist(书单)[];接着,用字符串变量name的equals()来一一比对,bookcase.booklist[]里,书籍的书名;最后,找到同名书籍后,用bookcase.getBooks(i)取得类Book的对象,用println(Book对象)调用toString()来打印对象。
 

▪删除书籍 - DelOperation  (delete:v,删除)

public class DelOperation implements Ioperation{ //这个类实现了接口
    public void work(Bookcase bookcase){
        System.out.println("-----删除书籍-----");
        //输入删除书籍的名称
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入删除书籍名称");
        String name = sc.nextLine();
        //调用对象bookcase的方法得到书架上书籍的数量,作为遍历结束的条件
        int usednumber = bookcase.getUsednumber();

        if(usednumber == 0){
            System.out.println("图书馆书籍为空");
            return;
        }

        for(int i=0; i<usednumber; i++){
           //在书架中寻找与借阅书籍名称相同的书籍
            if(name.equals(bookcase.getBooks(i).getName())){ 
                    //name.equals(str): 调用了字符串name的实例方法,来比较name是否与str同名
                    //bookcase.getBooks(i): 找到下标i对应的Book对象
                    //.getName(): 得到此Book对象的"书名"属性,这是一个字符串属性,即str
                System.out.println("删除成功");
                for(;i<usednumber;i++){
                    //用下标i+1的书籍来覆盖下标为i的书籍,既实现了对书籍的删除,又补上了删除后的空缺部分
                    bookcase.setBooks(i,bookcase.getBooks(i+1));
                }
                //因为i后面的书籍都被前移,最后的一本书籍会多余一本,要被清空
                bookcase.setBooks(usednumber,null);
                //书籍数量-1
                bookcase.setUsednumber(usednumber -= 1);
            }
        }
    }
}

        此方法传入一个类型为Bookcase的对象:bookcase。首先,用一个变量“name”来接收删除书名;然后,遍历bookcase的booklist(书单)[];再然后,用字符串变量name的equals()来一一比对,bookcase.booklist[]里,书籍的书名;接着,找到同名书籍后,用一个循环来将此书后方的书籍前移,前移的结果就是覆盖了此书起到删除作用,但booklist[]的最后一本书多出一本,即AXBCD -> ABCDD(BCD前移,覆盖了X,多余了D);最后,清除多余的D,再给“书籍数量”减1。


▮主函数main来启动项目

▪Main类 

public class Main {
    //功能:根据选项的不同,返回子类管理员或普通人
    public static User chose (){
        //输入User的name属性
        System.out.println("请输入你的名字");
        Scanner sc = new Scanner(System.in);
        String name = sc.nextLine();
        
        //选择身份
        System.out.println("请输入你的身份:1.管理员 2.普通人员");
        int i = sc.nextInt();
        //返回子类:管理员
        if(i == 1){
            return new AdminiUser(name); //new了一个对象
        //返回子类:普通人    
        }else if(i == 2){
            return new NomalUser(name);
        }
        return null;
    }
    
    //mian()函数
    public static void main(String[] args) { 
        //创建一个书架对象
        Bookcase Bookcase = new Bookcase();
        //创建一个父类User来接收子类,实现向上转型
        User user = chose();
        int chose = 0;
        //循环执行程序
        while(true){
            //nume()是一个被子类所重写的方法,这里实现了动态绑定,执行的是子类的menu方法
            //chose是一个整数,来接收你的选择
            chose = user.menu();
            //根据你的选择来执行对应的行为
            user.operation[chose].work(Bookcase);//chose作为下标,与对应的选项想呼应
        }
    }
}

        main()函数放在Main这个类中。首先,在main函数里定义了一个方法chose(),它是来让用户选择他的身份,并根据用户的选择来创建子类“管理员”或“普通人”对象,并把创建的子类作为chose()的返回值。

        然后,main创建了一个Bookcase的对象:bookcase,他就是一个默认构造了三本书的书架。接着,main定义了一个User类型的引用类型:user,并执行上面的chose()来得到对象;最后,main通过while循环,一直打印循环菜单和执行选项对应的功能。

▪管理员的菜单

public class AdminiUser extends User{
    //打印菜单,返回选项
    public int menu(){
        System.out.println('\n');
        Scanner sc = new Scanner(System.in);
        System.out.println("管理员:"+super.gteName()+",欢迎进入图书管理系统");
        System.out.println("0.退出系统");
        System.out.println("1.添加书籍");
        System.out.println("2.删减书籍");
        System.out.println("3.展示书籍");
        System.out.println("请选择你的操作:");
        return sc.nextInt();
    }
    //构造方法,非默认
    public AdminiUser(String name){
        super(name);
        operation = new Ioperation[]{ //菜单的选项与方法的下标所对应
                new ExitOperation(),
                new AddOperation(),
                new DelOperation(),
                new DisOperation(),
        };
    }
}

        菜单menu()方法会打印菜单,并且返回用户选择的选项值,由main中的chose变量接收。

▪普通人菜单

public class NomalUser extends User{
    //打印菜单,返回选项
    public int menu(){
        System.out.println('\n'); //打印双'\n'
        Scanner sc = new Scanner(System.in);
        System.out.println("普通人员:"+super.gteName()+",欢迎进入图书管理系统");
        System.out.println("0.退出系统");
        System.out.println("1.借阅书籍");
        System.out.println("2.归还书籍");
        System.out.println("3.查找书籍");
        System.out.println("请选择你的操作:");
        return sc.nextInt();
    }
    //构造方法,非默认
    public NomalUser(String name){
        super(name);
        super.operation = new Ioperation[]{
           new ExitOperation(),   //菜单的选项与方法的下标所对应
           new BorrowOperation(),
           new ReturnOperation(),
           new FindOperation(),
        };
    }
}

        菜单menu()方法会打印菜单,并且返回用户选择的选项值,由main中的chose变量接收。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值