簡易的動物園管理系統之Java8流式API的重構代碼(使用 狀態設計模式)

前言

原文鏈接:https://blog.csdn.net/FBB360JAVA/article/details/79256570
本文重在code review。
實現的只是一個簡易的管理系統,控制檯輸入、輸入。以及增刪改查等操作。

項目結構

在這裏插入圖片描述
在這裏插入圖片描述
其中 RunTest 是用來測試ZooManager的。
核心功能實現是在 ZooManager 中。

java 代碼

AbstractAnimal

package zoo.entity.base;

import java.io.*;
import java.util.Objects;

/**
 * 動物類
 * 注意:當動物名和動物類型一致時,認爲是同一個動物
 * @author Feng
 */
public abstract class AbstractAnimal implements Serializable {
    private static final long serialVersionUID = 799133399232518077L;
    /**動物的名字*/
    private String name;
    /**動物的類型*/
    private String type;

    public AbstractAnimal() {
    }

    public AbstractAnimal(String name) {
        type = getType();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 獲得動物的類類型
     * @return 返回當前對象的類的簡單名字(轉小寫)
     */
    public String getType() {
        return this.getClass().getSimpleName().toLowerCase();
    }

    public void setType(String type){
        this.type = type;
    }
    /**
     * 深克隆:需要序列化。
     * 爲後期擴展而寫(可能會用到,目前程序中沒有使用)
     */
    @Deprecated
    public AbstractAnimal deepClone() throws IOException, ClassNotFoundException {
        // 將對象寫入流中
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        // 將對象從流中取出
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (AbstractAnimal)(ois.readObject());
    }


    @Override
    public String toString() {
        return String.join("\t\t", name, type);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        AbstractAnimal that = (AbstractAnimal) o;
        return Objects.equals(name, that.name) &&
                Objects.equals(type, that.type);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, type);
    }
}

Cat

package zoo.entity;

import zoo.entity.base.AbstractAnimal;
import zoo.inter.Leg;

/**
 * 貓
 * @author Feng
 */
public class Cat extends AbstractAnimal implements Leg {
    private static final long serialVersionUID = -2919986919068143322L;

    public Cat() {
    }

    public Cat(String name) {
        super(name);
    }

    @Override
    public int getLegNum() {
        return 4;
    }
}

Dog

package zoo.entity;

import zoo.entity.base.AbstractAnimal;
import zoo.inter.Leg;

/**
 * 狗
 * @author Feng
 */
public class Dog extends AbstractAnimal implements Leg {
    private static final long serialVersionUID = -8956792508217398988L;

    public Dog() {
    }

    public Dog(String name) {
        super(name);
    }

    @Override
    public int getLegNum() {
        return 4;
    }
}

Leg

package zoo.inter;

/**
 * 腿
 * @author Feng
 */
public interface Leg {

    /**
     * 獲得腿的條數
     * @return 腿的數目
     */
    int getLegNum();

    default void run(){
        System.out.println("我用"+ getLegNum() + "條腿跑!");
    }
}

Swim

package zoo.inter;

/**
 * 游泳
 * @author Feng
 */
public interface Swim {
}

ZooManager

package zoo.manager;

import zoo.entity.base.AbstractAnimal;

import java.util.Collections;
import java.util.List;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
/**
 * 動物園管理者:
 * 設計爲單例,提供常用的方法來操作動物的信息
 */
public class ZooManager {
    private static ZooManager zooManager = null;

    private final List<AbstractAnimal> animalList;

    private ZooManager(List<AbstractAnimal> animalList) {
        this.animalList = animalList;
    }

    /**
     * 得到動物園管理者對象
     * @param animalList 動物列表
     */
    public static ZooManager manager(List<AbstractAnimal> animalList){
        if(zooManager == null){
            zooManager = new ZooManager(animalList);
        }

        return zooManager;
    }

    /**
     * 得到動物園管理者對象(動物列表爲空)
     * @return 管理者對象
     */
    public static ZooManager manager(){
        return manager(Collections.emptyList());
    }

    /**
     * 獲取所有動物信息
     * @return 所有動物列表
     */
    public List<AbstractAnimal> getAnimalList(){
        return animalList;
    }

    /**
     * 通過 Class 來獲取指定的類型的動物列表
     * @param abstractAnimalClass examples: Cat.class
     * @return 動物列表
     */
    public List<AbstractAnimal> getAnimalListByClass(Class<?> abstractAnimalClass){
        return animalList.stream()
                .filter(abstractAnimal -> abstractAnimal.getClass() == abstractAnimalClass)
                .collect(toList());
    }

    /**
     * 通過 type 字符串來獲取指定類型的動物列表
     * @param type examples: "cat"
     * @return 動物列表
     */
    public List<AbstractAnimal> getAnimalListByType(String type){
        return animalList.stream()
                .collect(groupingBy(AbstractAnimal::getType, toList()))
                .getOrDefault(type, Collections.emptyList());
    }

    /**
     * 通過動物的名字獲取動物列表(名字可能重複,因此結果是個列表)
     * @param name 動物的名字
     * @return 名字是 name 的所有的動物
     */
    public List<AbstractAnimal> getAnimalListByName(String name){
        return animalList.stream()
                .collect(groupingBy(AbstractAnimal::getName, toList()))
                .getOrDefault(name, Collections.emptyList());
    }

    /**
     * 增加一個動物
     * @param animal 任意一個動物
     */
    public boolean addAnimal(AbstractAnimal animal){
        return animalList.add(animal);
    }

    /**
     * 刪除動物
     * @param animal 動物對象
     */
    public boolean deleteAnimal(AbstractAnimal animal){
        return animalList.remove(animal);
    }


    /**
     * 修改動物信息(其實是一種暴力的方式,刪除了原先的舊的信息,將新的添加進去)
     * @param from 目標動物信息
     * @param to 新的動物信息
     * @return 修改成功返回 true
     */
    public boolean updateAnimal(AbstractAnimal from, AbstractAnimal to){
        if(containsAnimal(from)){
            deleteAnimal(from);
        }
        return addAnimal(to);
    }

    public boolean containsAnimal(AbstractAnimal animal){
       return animalList.contains(animal);
    }
}

RunTest

package zoo.client;

import zoo.entity.Cat;
import zoo.entity.Dog;
import zoo.entity.base.AbstractAnimal;
import zoo.manager.ZooManager;

import java.util.ArrayList;
import java.util.List;

/**
 * 運行:測試
 */
public class RunTest {
    public static void main(String[] args) {

        // 初始化數據
        final List<AbstractAnimal> animalList = new ArrayList<AbstractAnimal>(){
            private static final long serialVersionUID = -2569394013903999819L;
            {
                add(new Cat("Tom"));
                add(new Cat("Divid"));
                add(new Cat("Switch"));
                add(new Cat("小馮"));

                add(new Dog("愣娃"));
                add(new Dog("小馮"));
            }
        };

        // 獲得管理者
        ZooManager manager = ZooManager.manager(animalList);

        // 打印所有動物信息
        manager.getAnimalList().forEach(System.out::println);

        // 通過類得到指定類型的動物列表
        manager.getAnimalListByClass(Dog.class).forEach(System.out::println);

        // 通過名字獲取動物(可能重複)
        manager.getAnimalListByName("小馮").forEach(System.out::println);

        // 通過類型獲得動物列表
        manager.getAnimalListByType("cat").forEach(System.out::println);

        // 增加一個動物
        Cat cat = new Cat("小劉");
        manager.addAnimal(cat);
        // true
        System.out.println(manager.containsAnimal(cat));

        // 修改動物信息
        manager.updateAnimal(cat, new Cat("小小劉"));

        // 刪除:true
        System.out.println(manager.deleteAnimal(new Cat("小小劉")));
    }
}

Client

package zoo.client;

import zoo.entity.Cat;
import zoo.entity.Dog;
import zoo.entity.base.AbstractAnimal;
import zoo.manager.ZooManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * 客戶端
 * @author Feng
 */
public class Client {
    private static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

    /** 初始化數據*/
    private static final List<AbstractAnimal> ANIMAL_LIST = new ArrayList<AbstractAnimal>(){
        private static final long serialVersionUID = -2569394013903999819L;
        {
            add(new Cat("Tom"));
            add(new Cat("Divid"));
            add(new Cat("Switch"));
            add(new Cat("小馮"));

            add(new Dog("愣娃"));
            add(new Dog("小馮"));
        }
    };
    /** 創建管理者*/
    private final static ZooManager MANAGER = ZooManager.manager(ANIMAL_LIST);
    /** 初始化執行策略*/
    private final static Map<Integer, Consumer<String>> MAP = new HashMap<Integer, Consumer<String>>(16){

        private static final long serialVersionUID = 8594371374378459978L;
        {
            put(0, (title) -> {
                System.out.println(title);
                MANAGER.getAnimalList().forEach(System.out::println);
            });

            put(1, (title) -> {
                String type = in("請輸入你要查找的動物的類型(dog,cat):");
                System.out.println(title);
                MANAGER.getAnimalListByType(type).forEach(System.out::println);
            });

            put(2, (title) -> {
                String name = in("請輸入你要查找的動物的名字:");
                System.out.println(title);
                MANAGER.getAnimalListByName(name).forEach(System.out::println);
            });

            put(3, (title) -> {
                String name = in("請輸入你要增加的動物的名字:");
                String type = in("請是輸入你要增加的動物的類型:");
                AbstractAnimal animal = null;
                try {
                    animal = (AbstractAnimal)Class.forName("zoo.entity." + type.substring(0,1).toUpperCase() + type.substring(1)).newInstance();
                } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
                    e.printStackTrace();
                }

                if(animal != null){
                    animal.setName(name);
                    animal.setType(type);
                    if(MANAGER.containsAnimal(animal)){
                        System.out.println("該動物已經存在了,不能重複添加。");
                    } else {
                        MANAGER.addAnimal(animal);
                        System.out.println(name + "已經添加成功!");
                    }
                } else {
                    System.out.println("程序內部錯誤,可能是你輸入的動物類型不存在導致的。");
                }
            });

            put(4, (title) -> {
                String name = in("請輸入你要修改的動物的名字:");
                String type = in("請是輸入你要修改的動物的類型:");
                String newName = in("請輸入你要設置的新的動物的名字:");
                String newType = in("請是輸入你要設置的新的動物的類型:");

                try {
                    AbstractAnimal from = (AbstractAnimal)Class.forName("zoo.entity." + type.substring(0,1).toUpperCase() + type.substring(1)).newInstance();
                    from.setName(name);
                    from.setType(type);
                    AbstractAnimal to = (AbstractAnimal)Class.forName("zoo.entity." + newType.substring(0,1).toUpperCase() + newType.substring(1)).newInstance();
                    to.setName(newName);
                    to.setType(newType);

                    if(MANAGER.updateAnimal(from, to)){
                        System.out.println("已經修改成功了!");
                    } else {
                        System.out.println("請檢查你的輸入名或類型。");
                    }
                } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                    e.printStackTrace();
                }
            });

            put(5, (title) -> {
                String name = in("請輸入你要刪除的動物的名字:");
                String type = in("請是輸入你要刪除的動物的類型:");
                try {
                    AbstractAnimal animal = (AbstractAnimal) Class.forName("zoo.entity." + type.substring(0, 1).toUpperCase() + type.substring(1)).newInstance();
                    animal.setName(name);
                    animal.setType(type);
                    if(MANAGER.deleteAnimal(animal)){
                        System.out.println(name + "已經被刪除了!");
                    } else {
                        System.out.println("不存在該動物!請檢查你的輸入。");
                    }
                } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                    e.printStackTrace();
                }
            });
        }
    };

    public static void main(String[] args) {
        Client client = new Client();

        boolean isContinue = true;
        while (isContinue){
            String choose = client.runClient();

            switch (choose){
                case "0":
                    client.setStat(0);
                    break;
                case "1":
                    client.setStat(1);
                    break;
                case "2":
                    client.setStat(2);
                    break;
                case "3":
                    client.setStat(3);
                    break;
                case "4":
                    client.setStat(4);
                    break;
                case "5":
                    client.setStat(5);
                    break;
                    default:
                        isContinue = false;
                        break;
            }

            System.out.println("++++++++++++++++++++++++++++");
        }
    }

    private String runClient(){
        System.out.println("+++++++++++++zoo++++++++++++");
        System.out.println("\t0. 查看所有動物信息");
        System.out.println("\t1. 按動物類型查看");
        System.out.println("\t2. 按動物名查看");
        System.out.println("\t3. 增加一個動物");
        System.out.println("\t4. 修改一個動物");
        System.out.println("\t5. 刪除一個動物");
        System.out.println("\t 輸入其他任意鍵退出!");

        return in("請輸入你的選擇:");
    }


    /**
     * 控制檯打印tips,然後接收從鍵盤輸入的字符串
     * @param tips 提示信息
     * @return 鍵盤接收的字符串
     */
    private static String in(String tips){
        System.out.println(tips);
        String result = null;
        try {
            result = bufferedReader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 狀態設計模式
     * @param stat 狀態
     */
    private void setStat(int stat) {
        MAP.get(stat).accept("動物名\t\t動物類型");
    }
}

程序運行

正常運行使用 Client 類。
測試使用 RunTest。

結果展示

+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:
3
請輸入你要增加的動物的名字:
小晴
請是輸入你要增加的動物的類型:
cat
小晴已經添加成功!
++++++++++++++++++++++++++++
+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:
2
請輸入你要查找的動物的名字:
小晴
動物名		動物類型
小晴		cat
++++++++++++++++++++++++++++
+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:
4
請輸入你要修改的動物的名字:
小晴
請是輸入你要修改的動物的類型:
cat
請輸入你要設置的新的動物的名字:
小小晴
請是輸入你要設置的新的動物的類型:
cat
已經修改成功了!
++++++++++++++++++++++++++++
+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:
0
動物名		動物類型
Tom		cat
Divid		cat
Switch		cat
小馮		cat
愣娃		dog
小馮		dog
小小晴		cat
++++++++++++++++++++++++++++
+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:
5
請輸入你要刪除的動物的名字:
小小晴
請是輸入你要刪除的動物的類型:
cat
小小晴已經被刪除了!
++++++++++++++++++++++++++++
+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:
5
請輸入你要刪除的動物的名字:
小馮
請是輸入你要刪除的動物的類型:
cat
小馮已經被刪除了!
++++++++++++++++++++++++++++
+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:
0
動物名		動物類型
Tom		cat
Divid		cat
Switch		cat
愣娃		dog
小馮		dog
++++++++++++++++++++++++++++
+++++++++++++zoo++++++++++++
	0. 查看所有動物信息
	1. 按動物類型查看
	2. 按動物名查看
	3. 增加一個動物
	4. 修改一個動物
	5. 刪除一個動物
	 輸入其他任意鍵退出!
請輸入你的選擇:

最後

代碼寫完以後,我做的測試並不多,但基本功能都測試了。
還有就是各位大佬,求輕虐。

修改

Client 中的main方法

不使用 switch 語句了。

public static void main(String[] args) throws IOException {
        Client client = new Client();

        boolean isContinue = true;
        while (isContinue){
            String choose = client.runClient();
            try {
                // 此處也可使用正則匹配數字
                int key = Integer.parseInt(choose);
                if(MAP.containsKey(key)){
                    client.setStat(key);
                } else {
                    System.err.println("不支持的操作!錯誤的輸入:" + key);
                }
            }catch (Exception e){
                System.err.println("無效的輸入!程序需要退出嗎?(y退出,其他任意鍵重新進入選擇頁面。)");
                String str;
                if((str = bufferedReader.readLine()) != null){
                    if("y".equalsIgnoreCase(str)){
                        isContinue = false;
                    }
                }
            }

            System.out.println("++++++++++++++++++++++++++++");
        }
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章