Java进阶 1-2 枚举

目录

常量特定方法

职责链模式的枚举实现

状态机模式的枚举实现

多路分发

1、使用枚举类型实现分发

2、使用常量特定方法实现分发

3、使用EnumMap实现分发

4、使用二维数组实现分发


本笔记参考自: 《On Java 中文版》


常量特定方法

        在Java中,我们可以通过为每个枚举实例编写不同的方法,来赋予它们不同的行为。一个方式是在枚举类型中定义抽象方法,并在枚举实例中实现它:

【例子:为枚举实例编写方法】

import java.text.DateFormat;
import java.util.Date;

public enum ConstantSpecificMethod {
    DATE_TIME {
        @Override
        String getInfo() {
            return DateFormat.getDateInstance()
                    .format(new Date());
        }
    },
    CLASSPATH {
        @Override
        String getInfo() {// getenv()方法用于获取指定环境变量的值
            return System.getenv("CLASSPATH");
        }
    },
    VERSION {
        @Override
        String getInfo() { // 获取由输入指定的属性
            return System.getProperty("java.version");
        }
    };

    abstract String getInfo();

    public static void main(String[] args) {
        for (ConstantSpecificMethod csm : values())
            System.out.println(csm.getInfo());
    }
}

        程序执行的结果是:

        在这个例子中,我们通过关联的枚举实例来调用对应的方法,这通常被称为表驱动模式

        这里需要复习一点:在面向对象的编程中,不同的行为是和不同的类相关联的。而上述枚举的每个实例都拥有各自不同的行为,这就表明每个实例都相当于不同的类型(体现了多态)。它们的共同点在于它们的基类ConstantSpecificMethod

        但这并不意味着枚举实例能够等价于普通的类:

【例子:枚举实例和类之间的不同点】

enum LikeClasses {
    A {
        @Override
        void behavior() {
            System.out.println("A");
        }
    },
    B {
        @Override
        void behavior() {
            System.out.println("B");
        }
    },
    C {
        @Override
        void behavior() {
            System.out.println("C");
        }
    };

    abstract void behavior();
}

public class NotClasses {
//    void f1(LikeClasses.A instance) {
//    } // 不可行的操作
}

        编译器并不允许f1()的操作:将枚举实例作为类的类型进行使用。为了解释这一点,可以对程序进行反编译javap -c LikeClasses

反编译告诉我们,每个枚举元素都是LikeClasses的一个static final实例。实例无法作为类型进行使用。

        除此之外,不同于内部类,因为枚举实例是静态的,所以我们无法通过外部类LikeClasses直接访问其内部的枚举实例(具体而言,我们无法在非静态域中访问外部类的静态成员)。

(与匿名内部类相比,常量特定方法要显得更加简洁。)

        除此之外,常量特定方法也支持重写

【例子:重写常量特定方法】

public enum OverrideConstantSpecific {
    NUT, BOLT,
    WASHER {
        @Override
        public void f() {
            System.out.println("重写后的f()方法");
        }
    };

    void f() {
        System.out.println("默认的f()方法");
    }

    public static void main(String[] args) {
        for (OverrideConstantSpecific ocs : values()) {
            System.out.print(ocs + ": ");
            ocs.f();
        }
    }
}

        程序执行的结果是:

    这些特性使得我们在通常情况下,可以将枚举作为类来使用。

职责链模式的枚举实现

||| 职责链模式:先创建一批用于解决目标问题的不同方法,并将它们链式排列。当一个请求到达时,它会顺着这条“链”向下走,直到遇到可以解决当前请求的方法。

        下面的例子描述了一个邮局模型:使用常规方法处理信件,当前方法不可行时,尝试其他方法,直到无法处理该信件为止(称为“死信”)。

    可以将每种处理方法视作一种策略,策略的列表组成了一条职责链。

【例子:邮局模型】

import onjava.Enums;

import java.util.Iterator;

class Mail {
    enum GeneralDelivery {YES, NO1, NO2, NO3, NO4, NO5} // 是否使用常规方式处理

    enum Scannability {UNSCANNABLE, YES1, YES2, YES3, YES4} // 是否可以扫描

    enum Readability {ILLEGIBLE, YES1, YES2, YES3, YES4} // 是否可读

    enum Address {INCORRECT, OK1, OK2, OK3, OK4, OK5, OK6}

    enum ReturnAddress {MISSING, OK1, OK2, OK3, OK4, OK5}

    // 创建枚举变量
    GeneralDelivery generalDelivery;
    Scannability scannability;
    Readability readability;
    Address address;
    ReturnAddress returnAddress;
    static long counter = 0;
    long id = counter++;

    @Override
    public String toString() {
        return "邮件" + id;
    }

    public String details() {
        return toString() +
                ",一般交付:" + generalDelivery + ",地址是否可以扫描:" + scannability +
                "\n地址是否可读:" + readability + ",目标地址:" + address +
                "\n返还地址:" + returnAddress;
    }

    // 用于生成测试邮件:
    // (Enums类可见笔记 进阶1-1)
    public static Mail randomMail() {
        Mail m = new Mail();

        // 为枚举实例随机赋值:
        m.generalDelivery =
                Enums.random(GeneralDelivery.class);
        m.scannability =
                Enums.random(Scannability.class);
        m.readability =
                Enums.random(Readability.class);
        m.address =
                Enums.random(Address.class);
        m.returnAddress =
                Enums.random(ReturnAddress.class);

        return m;
    }

    // count无需修改,可以使用final
    public static Iterable<Mail> generator(final int count) {
        return new Iterable<Mail>() {
            int n = count;

            @Override
            public Iterator<Mail> iterator() {
                return new Iterator<Mail>() {
                    @Override
                    public boolean hasNext() {
                        return n-- > 0;
                    }

                    @Override
                    public Mail next() {
                        return randomMail();
                    }
                };
            }
        };
    }
}

public class PostOffice {
    // 使用职责链模式:
    enum MailHandler {
        GENERAL_DELIVERY {
            @Override
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值