6

优化if-else之Java枚举中的两个小技巧

 2 years ago
source link: http://www.lzhpo.com/article/161
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

还是按常规操作走一波

什么是枚举?

枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。

大部分人如何使用枚举?

e.g.大部分人都是直接就时一想到枚举,昂,我常量写在枚举中/静态常量。

public enum MenuType {    CATEGORY,    PAGE,    BUTTON}

1.枚举中的比对值

昂,这个名称我乱起的,哈哈哈,Because match,听到比对我就马上能够想到match,仅此而已,怎么舒服怎么来。

我们只需要传入WindingPolarizationTaskEnum的value,然后使用match方法,就可以返回我们需要的枚举类型了。

public enum WindingPolarizationTaskEnum {    HIGH_LOW_WITH_GROUND(0, "高压-低压及地"),    LOW_HIGH_WITH_GROUND(1, "低压-高压及地"),    HIGH_LOW_GROUND(2, "高压、低压-地"),    OTHER(3, "其它试验数据");    WindingPolarizationTaskEnum(Integer number, String desc) {        this.number = number;        this.desc = desc;    }    private Integer number;    private String desc;    /**     * 根据类型返回具体的WindingPolarizationTaskEnum     *     * @param number number     * @return WindingPolarizationTaskEnum     */    public static WindingPolarizationTaskEnum match(Integer number) {        for (WindingPolarizationTaskEnum item : WindingPolarizationTaskEnum.values()) {            if (item.number.equals(number)) {                return item;            }        }        return WindingPolarizationTaskEnum.HIGH_LOW_WITH_GROUND;    }    public Integer getNumber() {        return number;    }    public void setNumber(Integer number) {        this.number = number;    }    public String getDesc() {        return desc;    }    public void setDesc(String desc) {        this.desc = desc;    }}

2.其实枚举类型中是可以定义方法的

demo1

来看一下我在学校时期写的一段代码...注释上都有,就不重复解释了。

import com.data.DataService;import com.model.msgtype.opendevicealarmtype.OpenDeviceAlarm;import com.model.msgtype.opendeviceonofflinetype.OpenDeviceOnoffline;import com.model.msgtype.openeventaccessbatchdeliveredtype.OpenEventAccessBatchDelivered;import com.model.msgtype.openeventaccesstype.OpenEventAccess;import com.model.msgtype.openeventsuperbrainfacesdeliveredtype.OpenEventSuperBrainFacesDelivered;import com.model.msgtype.openezvizdetectoralarmtype.OpenEzvizDetectorAlarm;import com.model.msgtype.openfacecapturetype.OpenFaceCapture;import com.model.msgtype.openidcardeventtype.OpenIdcardEvent;import com.model.msgtype.openmessageanpr.OpenMessageAnpr;import com.model.msgtype.openmessagetma.OpenMessageTma;import com.model.msgtype.openpassengerflowtype.OpenPassengerFlow;import com.model.msgtype.openpersonqueuecountingtype.OpenPersonQueueCounting;import com.response.ErrorCode;import com.response.hkym.CommonObj;import com.util.JsonUtil;import java.io.IOException;/** * 消息类型 * <p> * 我想到的优化(if-else、switch)的解决方案: * 1. 使用容器,每个方法都换成一个类,但这样的话,就要多加很多个类 * 2. 使用反射,但是反射的速度太慢了。 * 3. 使用函数式接口,使用函数式接口作为容器的元素。 * 4. 用Runnable。 * 5. 设计模式(状态模式、策略模式、工厂模式) * 6. 枚举 + 方法。 * </p> * @author lzhpo */public enum MsgTypeEnum {    /** 门禁事件消息 */    OPEN_EVENT_ACCESS("open_event_access") {        @Override        OpenEventAccess run(String content) throws IOException {            System.out.println("门禁事件消息:" +content);            return JsonUtil.parse(content, OpenEventAccess.class);        }    },    /** 人证比对事件 */    OPEN_IDCARD_EVENT("open_idcard_event") {        @Override        OpenIdcardEvent run(String content) throws IOException {            System.out.println("人证比对事件:" +content);            return JsonUtil.parse(content, OpenIdcardEvent.class);        }    },    /** 客流消息 */    OPEN_PASSENGERFLOW("open_passengerFlow") {        @Override        OpenPassengerFlow run(String content) throws IOException {            System.out.println("客流消息:" +content);            OpenPassengerFlow openPassengerFlow = JsonUtil.parse(content, OpenPassengerFlow.class);            DataService.leave += openPassengerFlow.getLeaveNum();            DataService.enter += openPassengerFlow.getEnterNum();            DataService.pass += openPassengerFlow.getLeaveNum() + openPassengerFlow.getEnterNum();            openPassengerFlow.setEnterNum(DataService.enter);            openPassengerFlow.setLeaveNum(DataService.leave);            openPassengerFlow.setPassNum(DataService.pass);            return openPassengerFlow;        }    },    /** 人脸抓拍消息 */    OPEN_FACE_CAPTURE("open_face_capture") {        @Override        OpenFaceCapture run(String content) throws IOException {            System.out.println("人脸抓拍消息:" +content);            return JsonUtil.parse(content, OpenFaceCapture.class);        }    },    /** 门禁批量下发消息 */    OPEN_EVENT_ACCESS_BATCH_DELIVERED("open_event_access_batch_delivered") {        @Override        OpenEventAccessBatchDelivered run(String content) throws IOException {            System.out.println("门禁批量下发消息:" +content);            return JsonUtil.parse(content, OpenEventAccessBatchDelivered.class);        }    },    /** 超脑人脸下发消息 */    OPEN_EVENT_SUPER_BRAIN_FACES_DELIVERED("open_event_super_brain_faces_delivered") {        @Override        OpenEventSuperBrainFacesDelivered run(String content) throws IOException {            System.out.println("超脑人脸下发消息:" +content);            return JsonUtil.parse(content, OpenEventSuperBrainFacesDelivered.class);        }    },    /** 超脑人脸比对消息 */    OPEN_EVENT_SUPER_BRAIN_FACES_COMPARISON("open_event_super_brain_faces_comparison") {        @Override        OpenEventSuperBrainFacesDelivered run(String content) throws IOException {            System.out.println("超脑人脸比对消息:" +content);            return JsonUtil.parse(content, OpenEventSuperBrainFacesDelivered.class);        }    },    /** 萤石探测器报警消息 */    OPEN_EZVIZ_DETECTOR_ALARM("open_ezviz_detector_alarm") {        @Override        OpenEzvizDetectorAlarm run(String content) throws IOException {            System.out.println("萤石探测器报警消息:" +content);            return JsonUtil.parse(content, OpenEzvizDetectorAlarm.class);        }    },    /** 设备报警消息 */    OPEN_DEVICE_ALARM("open_device_alarm") {        @Override        OpenDeviceAlarm run(String content) throws IOException {            System.out.println("设备报警消息:" +content);            return JsonUtil.parse(content, OpenDeviceAlarm.class);        }    },    /** 设备上下线消息 */    OPEN_DEVICE_ONOFFLINE("open_device_onoffline") {        @Override        OpenDeviceOnoffline run(String content) throws IOException {            System.out.println("设备上下线消息:" +content);            return JsonUtil.parse(content, OpenDeviceOnoffline.class);        }    },    /** 车辆抓拍消息 */    OPEN_MESSAGE_ANPR("open_message_anpr") {        @Override        OpenMessageAnpr run(String content) throws IOException {            System.out.println("车辆抓拍消息:" +content);            return JsonUtil.parse(content, OpenMessageAnpr.class);        }    },    /** 测温报警消息 */    OPEN_MESSAGE_TMA("open_message_tma") {        @Override        OpenMessageTma run(String content) throws IOException {            System.out.println("测温报警消息:" +content);            return JsonUtil.parse(content, OpenMessageTma.class);        }    },    /** 区域人数超限报警消息 */    OPEN_PERSON_QUEUE_COUNTING("open_person_queue_counting") {        @Override        OpenPersonQueueCounting run(String content) throws IOException {            System.out.println("区域人数超限报警消息:" +content);            return JsonUtil.parse(content, OpenPersonQueueCounting.class);        }    };    private String type;    MsgTypeEnum() {    }    MsgTypeEnum(String type) {        this.type = type;    }    public String getType() {        return type;    }    public void setType(String type) {        this.type = type;    }    /** 定义枚举的方法 */    abstract <T> T run(String content) throws IOException;    /**     * 比对消息类型,然后执行run方法,返回对应的content值     *     * @param type 消息类型     * @param content 消息类型对应的内容     * @return map 消息类型和消息类型对应的content数据     */    public static <T> CommonObj<T> matchTypeRun(String type, String content) throws IOException {        for (MsgTypeEnum item : MsgTypeEnum.values()) {            if (item.type.equals(type)) {                CommonObj<T> commonObj = new CommonObj<>();                commonObj.setCode(ErrorCode.SUCCESS.code);                commonObj.setSuccess(Boolean.TRUE);                // 设置消息类型                commonObj.setMessage(type);                // 设置消息数据                commonObj.setData(item.run(content));                return commonObj;            }        }        return new CommonObj<>(ErrorCode.FAIL.code, "获取消息数据失败", false);    }}
CommonObj<Object> msgContentObj = MsgTypeEnum.matchTypeRun(consumeMsg.getMsgType(), consumeMsg.getContent());

MsgTypeEnum中,我定义了一个抽象枚举方法run,在枚举类型中实现了run方法。

这里主要是根据传入的数据类型进行不同的反序列化,然后再返回。

demo2

可能上面的有泛型,为了方便各位理解,我再来一个没有泛型的,帮助各位理解一下。

import com.withive.project.tools.file.entity.DebugCorrelationFile;/** * 文件关联的类型 * * @author Zhaopo Liu */public enum DbgFileType {    /**     * 设备参数     */    DEVICE_PARAMS(0) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .deviceParamsId(correlationId)                    .build();        }    },    /**     * 测量绕组连同套管的直流电阻     */    WINDING_TASK(1) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .windingTaskId(correlationId)                    .build();        }    },    /**     * 所有分接头的电压比及三相组别ID     */    TAP_THREE_TEST_TASK(2) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .tapThreeTestTaskId(correlationId)                    .build();        }    },    /**     * 绕组连同套管的绝缘电阻、吸收比或极化指数     */    WINDING_POLARIZATION_TASK(3) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .windingPolarizationTaskId(correlationId)                    .build();        }    },    /**     * 介质损耗及电容值测试     */    MEDIUM_CAPACITANCE_LOSS(4) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .mediumCapacitanceLossId(correlationId)                    .build();        }    },    /**     * 绕组连同套管的交流耐压试验     */    WINDING_AC_TASK(5) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .windingAcTaskId(correlationId)                    .build();        }    },    /**     * 与铁心绝缘的各紧固件及铁心的绝缘电阻     */    IRON_FASTENERS_INSULATION_TASK(6) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .ironFastenersInsulationTaskId(correlationId)                    .build();        }    },    /**     * 绕组变形(电抗法)     */    WINDING_DEFORMATION_TASK(7) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .windingDeformationTaskId(correlationId)                    .build();        }    },    /**     * 试验结论     */    DEBUG_TASK(8) {        @Override        DebugCorrelationFile run(Long fileId, Long correlationId) {            return DebugCorrelationFile.builder()                    .fileId(fileId)                    .debugTaskId(correlationId)                    .build();        }    };    private Integer type;    DbgFileType() {    }    DbgFileType(Integer type) {        this.type = type;    }    public Integer getType() {        return type;    }    public void setType(Integer type) {        this.type = type;    }    /**     * 定义抽象方法     */    abstract DebugCorrelationFile run(Long fileId, Long correlationId);    /**     * 比对消息类型,然后执行run方法,返回对应的DebugCorrelationFile{@link DebugCorrelationFile}     *     * @param dbgType 试验类型     * @param fileId 文件ID     * @param correlationId 哪个试验项目的ID     * @return DebugCorrelationFile     */    public static DebugCorrelationFile matchTypeRun(Integer dbgType, Long fileId, Long correlationId) {        for (DbgFileType item : DbgFileType.values()) {            if (item.type.equals(dbgType)) {                return item.run(fileId, correlationId);            }        }        return null;    }}

DbgFileType中,我写了一个抽象方法run,它需要传入文件ID和实验项目的ID。

matchTypeRun中,我传入的参数就多了一个dbgType,也就是DbgFileType的枚举值,这里就将我前面说的match方法,传入枚举值,返回枚举类型,枚举类型中实现了我定义的抽象方法run,最终返回我需要的DebugCorrelationFile

使用demo:

DebugCorrelationFile debugCorrelationFile = DbgFileType.matchTypeRun(dbgFileTypeNum, entity.getId(), correlationId);

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK