首页 > 其他分享 >1.10 常量特定方法

1.10 常量特定方法

时间:2025-01-01 12:28:48浏览次数:8  
标签:case return 常量 1.10 特定 mail Override Input public


Java的枚举机制可以通过为每个枚举实例编写不同的方法,来赋予它们不同的行为。

package www.com.cat.chapter01;  
  
import java.util.Arrays;  
  
public enum ConstantSpecificMethod {  
    QU {  
        @Override  
        void action() {  
            System.out.println("生死喧嚣,归于寂静");  
        }  
    },  
    SUOLONG {  
        @Override  
        void action() {  
            System.out.println("三千世界");  
        }  
    };  
  
    abstract void action();  
  
    public static void main(String[] args) {  
        Arrays.stream(values()).forEach(ConstantSpecificMethod::action);  
    }  
}
输出 : 
生死喧嚣,归于寂静
三千世界

你可以通过关联的枚举实例来查找和调用方法,这通常叫做表驱动模式
枚举的各种实例可以拥有各自的行为,这表明每个实例都是不同的类型。

package www.com.cat.chapter01;  
  
import java.util.EnumMap;  
import java.util.EnumSet;  
  
public class People {  
    enum Ninja{  
        YOU {  
            @Override  
            void action() {  
                System.out.println("月读");  
            }  
        },  
        DAITU {  
            @Override  
            void action() {  
                System.out.println("神威");  
            }  
        },  
        KAKAXI {  
            @Override  
            void action() {  
                System.out.println("雷切");  
            }  
        },  
        MINGREN {  
            @Override  
            void action() {  
                System.out.println("螺旋丸");  
            }  
        };  
        abstract void action();  
    }  
  
    EnumSet<Ninja> ninjas = EnumSet.noneOf(Ninja.class);  
    public void add(Ninja ninja) {  
        ninjas.add(ninja);  
    }  
  
    public void ninjasAction() {  
        ninjas.stream().forEach(Ninja::action);  
    }  
  
  
    @Override  
    public String toString() {  
        return ninjas.toString();  
    }  
  
    public static void main(String[] args) {  
        People people = new People();  
        System.out.println(people);  
        people.add(Ninja.DAITU);  
        people.ninjasAction();  
        people.add(Ninja.MINGREN);  
        people.add(Ninja.KAKAXI);  
        people.add(Ninja.YOU);  
        people.add(Ninja.DAITU);  
        System.out.println(people);  
        people.ninjasAction();  
    }  
}
输出 : 
[]
神威
[YOU, DAITU, KAKAXI, MINGREN]
月读
神威
雷切
螺旋丸

添加枚举实例的顺序并不重要–输出顺序由枚举声明的顺序决定。

1.10.1 用枚举实现职责链模式


职责链(Chain of Responsibility)设计模式先创建了一批用于解决目标问题的不同方法,然后将它们连成一条"链"。当一个请求到达时,就会顺着这条链传递下去,直到链上某个可以处理该请求的方法。

这么长的代码写得我心儿都碎了。

package www.com.cat.chapter01;  
  
import java.util.*;  
import java.util.function.Consumer;  
import java.util.stream.Collectors;  
  
@SuppressWarnings("all")  
class Mail {  
    enum Hero {  
        QU, LUXIYA, LUNA, HANYING, QISHI, LUOSAITA;  
    }  
  
    enum JoJo {  
        KIllERQUEEN, STARPLATINUM, THEWORLD, GOLDEXPERIENCE, HEAVENSDOOR;  
    }  
  
    enum Ninja {  
        ZUOZHU, MINGREN, ZILAIYE, WOAILUO, BAN, KAI;  
    }  
  
    enum HaiZei {  
        SUOLONG, LUFEI, SHANZHI, MIHUOKE, BAJI;  
    }  
  
    enum BuLiangRen {  
        LIXINYUN, JIRUXUE, CHIMENG, YUANTIANGANG, LIMANGZHEN;  
    }  
  
  
    Hero hero;  
    JoJo jojo;  
    Ninja ninja;  
    HaiZei haizei;  
    BuLiangRen buliangren;  
    static long counter = 0;  
    long id = counter++;  
  
    @Override  
    public String toString() {  
        return "Mail" + id;  
    }  
  
    public String details() {  
        return "Hero : " + hero + ", jojo : " + jojo + ", ninja : " + ninja + ", haizei : " + haizei + ", buliangren : " + buliangren;  
    }  
  
    // 生成测试邮件  
    public static Mail randomMail() {  
        Mail mail = new Mail();  
        mail.hero = Enums.random(Hero.class);  
        mail.jojo = Enums.random(JoJo.class);  
        mail.ninja = Enums.random(Ninja.class);  
        mail.haizei = Enums.random(HaiZei.class);  
        mail.buliangren = Enums.random(BuLiangRen.class);  
        return mail;  
    }  
  
    public static Iterable<Mail> generator(final int count) {  
        return new Iterable<Mail>() {  
            int total = count;  
  
            @Override  
            public Iterator<Mail> iterator() {  
                return new Iterator<Mail>() {  
                    @Override  
                    public boolean hasNext() {  
                        return total-- > 0;  
                    }  
  
                    // 生成一个随机的护送列表  
                    @Override  
                    public Mail next() {  
                        return randomMail();  
                    }  
                };  
            }  
        };  
    }  
}  
  
@SuppressWarnings("all")  
public class Delivery {  
    enum MailHandler {  
        HeroHan {  
            @Override  
            boolean check(Mail mail) {  
                switch (mail.hero) {  
                    case QU:  
                    case LUNA:  
                    case HANYING:  
                    case QISHI:  
                        return true;  
                    default:  
                        System.out.println("Error : " + mail.hero);  
                        return false;  
                }  
            }  
        },  
        JoJoHan {  
            @Override  
            boolean check(Mail mail) {  
                switch (mail.jojo) {  
                    case STARPLATINUM:  
                    case KIllERQUEEN:  
                    case GOLDEXPERIENCE:  
                    case THEWORLD:  
                        return true;  
                    default:  
                        System.out.println("Error : " + mail.jojo);  
                        return false;  
                }  
            }  
        },  
        NinjaHan {  
            @Override  
            boolean check(Mail mail) {  
                switch (mail.ninja) {  
                    case ZUOZHU:  
                    case MINGREN:  
                    case BAN:  
                    case KAI:  
                        return true;  
                    default:  
                        System.out.println("Error : " + mail.ninja);  
                        return false;  
                }  
            }  
        },  
        HaiZeiHan {  
            @Override  
            boolean check(Mail mail) {  
                switch (mail.haizei) {  
                    case SUOLONG:  
                    case LUFEI:  
                    case SHANZHI:  
                    case MIHUOKE:  
                        return true;  
                    default:  
                        System.out.println("Error : " + mail.haizei);  
                        return false;  
                }  
            }  
        },  
        BuLiangRenHan {  
            @Override  
            boolean check(Mail mail) {  
                switch (mail.buliangren) {  
                    case LIXINYUN:  
                    case JIRUXUE:  
                    case YUANTIANGANG:  
                    case LIMANGZHEN:  
                        return true;  
                    default:  
                        System.out.println("Error : " + mail.buliangren);  
                        return false;  
                }  
            }  
        };  
  
        abstract boolean check(Mail mail);  
    }  
  
    public static void handle(Mail mail) {  
        for (MailHandler handler : MailHandler.values()) {  
            if (!handler.check(mail)) {  
                return;  
            }  
        }  
        System.out.println("Successful!!!");  
    }  
  
    public static void main(String[] args) {  
        for (Mail mail : Mail.generator(10)) {  
            System.out.println(mail.details());  
            handle(mail);  
            System.out.println("*******************************");  
        }  
    }  
}

输出 : 
Hero : QU, jojo : KIllERQUEEN, ninja : ZUOZHU, haizei : SHANZHI, buliangren : JIRUXUE
Successful!!!
*******************************
Hero : LUOSAITA, jojo : KIllERQUEEN, ninja : KAI, haizei : SUOLONG, buliangren : LIXINYUN
Error : LUOSAITA
*******************************
Hero : LUOSAITA, jojo : HEAVENSDOOR, ninja : WOAILUO, haizei : SUOLONG, buliangren : YUANTIANGANG
Error : LUOSAITA
*******************************
Hero : QU, jojo : GOLDEXPERIENCE, ninja : BAN, haizei : BAJI, buliangren : LIMANGZHEN
Error : BAJI
*******************************
Hero : HANYING, jojo : GOLDEXPERIENCE, ninja : KAI, haizei : BAJI, buliangren : YUANTIANGANG
Error : BAJI
*******************************
Hero : LUNA, jojo : HEAVENSDOOR, ninja : ZUOZHU, haizei : LUFEI, buliangren : CHIMENG
Error : HEAVENSDOOR
*******************************
Hero : HANYING, jojo : GOLDEXPERIENCE, ninja : BAN, haizei : SHANZHI, buliangren : JIRUXUE
Successful!!!
*******************************
Hero : LUOSAITA, jojo : STARPLATINUM, ninja : WOAILUO, haizei : SUOLONG, buliangren : CHIMENG
Error : LUOSAITA
*******************************
Hero : QU, jojo : GOLDEXPERIENCE, ninja : ZILAIYE, haizei : SHANZHI, buliangren : JIRUXUE
Error : ZILAIYE
*******************************
Hero : LUNA, jojo : HEAVENSDOOR, ninja : ZILAIYE, haizei : SHANZHI, buliangren : LIMANGZHEN
Error : HEAVENSDOOR
*******************************

其实我写的程序功能比书上稍微强大一点,我的程序会打印出在职责链上是谁没有成功完成任务

职责链模式的作用体现在了MainHandler枚举中,枚举的定义顺序则决定了各个策略在每封邮件上被应用的顺序。该模式会按顺序尝试应用每个策略,直到某个策略执行成功,或者全部策略都执行失败。

1.10.2 用枚举实现状态机


枚举类型很适合用来实现状态机。状态机可以处于有限数量的特定状态。它们通常根据输入,从一个状态移动到下一个状态,但同时也会存在瞬态。当任务执行完毕后,状态机会立即跳出所有状态

个人认为这本书最大的缺点就是示例代码给的太长,也太难了。没有基础的话看这么长这么难的代码,看得心都碎了,就算有基础的话,看起来也很累。

package www.com.cat.chapter01;  
  
import java.util.Random;  
  
public enum Input {  
    NICKEL(5), DIME(10), QUARTER(25), DOLLAR(100), TOOTHPASTE(200), CHIPS(75), SODA(100), SOAP(50),  
    ABORT_TRANSACTION {  
        @Override  
        int amount() {  
            throw new RuntimeException("ABORT_TRANSACTION.amount()");  
        }  
    },  
    STOP {  
        @Override  
        int amount() {  
            throw new RuntimeException("STOP.amount()");  
        }  
    };  
    int value;  
  
    Input(int value) {  
        this.value = value;  
    }  
  
    Input() {  
    }  
    int amount() {  
        return value;  
    }  
  
    static Random random = new Random(13);  
  
    public static Input randomSelection() {  
        // 不存在stop  
        return values()[random.nextInt(values().length - 1)];  
    }  
}

下面是一个自动售卖机的例子

我的代码很长,你忍一下

package www.com.cat.chapter01;  
  
import java.io.IOException;  
import java.nio.file.Files;  
import java.nio.file.Path;  
import java.nio.file.Paths;  
import java.util.Arrays;  
import java.util.EnumMap;  
import java.util.Iterator;  
import java.util.function.Supplier;  
import java.util.stream.Collectors;  
import java.util.stream.IntStream;  
import java.util.stream.Stream;  
  
@SuppressWarnings("all")  
// 为原来能对自动售卖机的操作分类  
// 使用了Category来达到分类的目的  
enum Category {  
    // 收钱  
    MONEY(Input.DIME, Input.DOLLAR, Input.NICKEL, Input.QUARTER),  
    // 能购买的物品  
    ITEM(Input.TOOTHPASTE, Input.SODA, Input.SOAP, Input.CHIPS),  
    // 退出  
    QUIT(Input.ABORT_TRANSACTION),  
  
    SHUTDOWN(Input.STOP);  
  
    Input[] inputs;  
  
    Category(Input... inputs) {  
        this.inputs = inputs;  
    }  
  
    private static EnumMap<Input, Category> categories = new EnumMap<>(Input.class);  
  
    static {  
//        for (Category category : Category.class.getEnumConstants()) {  
//            for (Input input : category.inputs) {  
//                categories.put(input, category);  
//            }  
//        }  
        // 下面的流操作与上面的for循环功能一致  
        Arrays.stream(Category.class.getEnumConstants()).  
                forEach(category -> Arrays.stream(category.inputs).  
                        forEach(input -> categories.put(input, category)));  
        System.out.println(categories);  
    }  
    // 得到这个input的操作类型  
    public static Category categorize(Input input) {  
        return categories.get(input);  
    }  
}  
  
@SuppressWarnings("all")  
// 下面这两个类都是用来输入指令的,这个使用文件来输入指令  
class FileInputSupplier implements Supplier<Input> {  
    private Iterator<String> input;  
    public FileInputSupplier(String filename) {  
        try {  
            // 文件会以特定的格式存在  
            input = Files.lines(Paths.get(filename)).skip(1).   // 跳过注释行  
                    flatMap(s -> Arrays.stream(s.split(";"))).  // 得到一行的内容,这行有多个指令以;分隔,首先将行以;切割,这会得到多个流,再将流合并  
                    map(String::trim).collect(Collectors.toList()).iterator();  // 去除空格和换行,将每一行的内容都收集到一个List中,再将这个List的迭代器返回。  
        } catch (IOException e) {  
            throw new RuntimeException(e);  
        }  
    }  
    // 获得一个指令  
    @Override  
    public Input get() {  
        // 没有指令就返回null  
        if (!input.hasNext()) {  
            return null;  
        }  
        String next = input.next().trim().replace('-', '_');  
        // 返回一个指令,因为指令是一字符串的形式存在的,所以将其转换成Input类型  
        return Enum.valueOf(Input.class, next);  
    }  
}  
  
class RandomInputSupplier implements Supplier<Input> {  
    @Override  
    public Input get() {  
        // 随机获得一个指令  
        return Input.randomSelection();  
    }  
}  
  
@SuppressWarnings("all")  
// 自动售卖机类  
public class VendingMachine {  
    private static State state = State.RESTING;  
    // amount : 记录客户投进自动售卖机的钱  
    private static int amount = 0;  
    // 将要执行的指令  
    private static Input selection = null;  
    // 是否为瞬态  
    enum StateDuration {  
        TRANSIENT;  
    }  
  
    enum State {  
        // 初始态,此时直接接受投币和退出操作  
        RESTING {  
            @Override  
            void next(Input input) {  
                switch (Category.categorize(input)) {  
                    case MONEY: // 投币后状态转为ADDING_MONEY  
                        amount += input.amount();  
                        state = ADDING_MONEY;  
                        break;  
                    case SHUTDOWN:  
                        state = TERMINAL;  
                    default:    // 其他类型指令不响应  
                }  
            }  
        },  
        // 已投币态  
        ADDING_MONEY {  
            @Override  
            void next(Input input) {  
                // 取出是哪一种状态,究竟是买东西还是给钱还是终止操作  
                switch (Category.categorize(input)) {  
                    case MONEY: // 一次可以投多枚硬币,所以状态不用变仍然保持ADDING_MONEY就好  
                        amount += input.amount();  
                        break;  
                    case ITEM:  // 选择物品  
                        selection = input;   // 买东西,selection指向被选中的物品  
                        if (amount < selection.amount()) {  // 投进去的钱不够,此时还需要投更多的钱,故状态仍然保持不变  
                            System.out.println("Insufficient money for " + selection);  
                        } else {  
                            state = DISPENSING; // 把东西给顾客  
                        }  
                        break;  
                    case QUIT:  // 不买了  
                        state = GIVING_CHANGE;  // 把剩余的钱还给顾客  
                        break;  
                    case SHUTDOWN:  // 关闭  
                        state = TERMINAL;  
                    default:    // 其余的指令不响应  
                }  
            }  
        },  
        // 交货态  
        DISPENSING(StateDuration.TRANSIENT) {  
            @Override  
            void next() {  
                System.out.println("Here is your " + selection);    // 把货物给顾客  
                amount -= selection.amount();   // 还剩下多少钱,在进入这个状态之前就已经确认过钱够不够了(见ADDING_MONEY)  
//                state = GIVING_CHANGE;  // 其实这里不用着急吐钱出来,这样一次就只能买一个物品,显得机器很蠢  
                state = ADDING_MONEY;   // 应该再次回到已投币态,在那里选择退出,或接着投币买更多东西  
            }  
        },  
        // 找零态  
        GIVING_CHANGE(StateDuration.TRANSIENT) {  
            @Override  
            void next() {  
                if (amount > 0) {  
                    System.out.println("Your change : " + amount);  // 把剩下的钱全部交给顾客  
                    amount = 0; // 将钱清零  
                }  
                state = RESTING;    // 回到初始状态  
            }  
        },  
        TERMINAL {  // 终止态  
            @Override  
            void output() {  
                System.out.println("Halted");  
            }  
        };  
  
        private boolean isTransient = false;  
  
        State() {  
        }  
        State(StateDuration trans) {  
            isTransient = true;  
        }  
        // 如果是枚举实例没有重写这这两个方法就直接抛出异常  
        void next(Input input) {  
            System.out.println(state);  
            throw new RuntimeException("Only call" + "next(Input input) for non-transient state");  
        }  
  
        void next() {  
            throw new RuntimeException("Only call " + "next() for StateDuration.TRANSIENT states");  
        }  
  
        void output() {  
            System.out.println(amount);  
        }  
    }  
  
    static void run(Supplier<Input> supplier) {  
        while (state != State.TERMINAL) {   // 不是终止态就一直运行  
            state.next(supplier.get()); // state一开始是初始态,此时它从supplier获取一个指令  
            while (state.isTransient) {     // 进入这个状态之后,它不会保持在这个状态  
                state.next();  
            }  
            state.output(); // 打印出当前状态下有多少钱  
        }  
    }  
  
    public static void main(String[] args) {  
        Supplier<Input> supplier = new RandomInputSupplier();  
        if (args.length == 1) {  
            supplier = new FileInputSupplier(args[0]);  
        }  
        run(supplier);  
//        IntStream.rangeClosed(1, 20).forEach(x -> System.out.println(supplier.get()));  
    }  
}

输出 : 
{NICKEL=MONEY, DIME=MONEY, QUARTER=MONEY, DOLLAR=MONEY, TOOTHPASTE=ITEM, CHIPS=ITEM, SODA=ITEM, SOAP=ITEM, ABORT_TRANSACTION=QUIT, STOP=SHUTDOWN}
25
50
75
Here is your CHIPS
0
100
200
Here is your TOOTHPASTE
0
25
35
Your change : 35
0
25
35
Insufficient money for SODA
35
60
70
75
Insufficient money for SODA
75
Your change : 75
0
Halted

输入文件 : 
// 为了与书上保持一致写的
QUARTER;QUARTER;QUARTER;CHIPS;
DOLLAR;DOLLAR;TOOTHPASTE;
QUARTER;DIME;ABORT-TRANSACTION;
QUARTER;DIME;SODA;
QUARTER;DIME;NICKEL;SODA;
ABORT-TRANSACTION;
STOP;

标签:case,return,常量,1.10,特定,mail,Override,Input,public
From: https://blog.csdn.net/StarPlatinum2/article/details/144825338

相关文章

  • Everything(文件快速搜索工具)v1.4.1.1026
    Everything是速度最快的文件搜索软件,可以瞬间搜索到你需要的文件。如果你用过Windows自Everything是速度最快的文件搜索软件,可以瞬间搜索到你需要的文件。如果你用过Windows自带的搜索工具、TotalCommander的搜索、Google桌面搜索或百度硬盘搜索,都因为速度或其他原因而不满意;或......
  • PHP 中的魔术常量
    概述PHP提供了9个魔术常数,您可以在PHP应用程序代码中使用。它们是“神奇的”,因为它们是在编译时定义的,不像常规常量(您可以自己定义)是在运行时定义的。这意味着它们的值可以根据它们在代码中的使用位置而更改。FUNCTION__FUNCTION__魔术常量返回使用它的函数的名称。如果在函......
  • 浅谈大模型私有化+精调:面向垂直行业与特定场景之需
    今天探讨大模型的私有化和精调,以便让预训练的通用模型更好地适应特定的任务或行业需求。当然,从产品经理的视角出发,我们不会非常深入(鄙人能力也有限),而是建立相关的基本认知。个人观点仅供参考,欢迎评论区补充、斧正~预警:全文约1万字,且比较偏技术&理论。如果你只是想了解下......
  • 如何从服务器上下载特定文件(如 www 下的压缩包)?
    若要从服务器上下载特定文件,比如www下的压缩包,首先需要确定服务器的访问方式和权限。如果服务器开启了相应的文件共享服务或者提供了FTP访问权限,可以使用FTP客户端软件进行连接和下载。在连接FTP服务器时,需要输入正确的FTP账号和密码(如果有),然后导航到服务器上的www目......
  • 如何在canvas画布上特定位置监听鼠标事件?
    在HTML5的Canvas元素上监听特定位置的鼠标事件稍微有些复杂,因为Canvas本身是一个像素画布,它不像DOM元素那样具有内置的事件处理机制来直接处理特定位置的事件。不过,你可以通过监听Canvas元素的鼠标事件,并在事件处理函数中检查鼠标的位置来实现类似的功能。以下是一个简单的示例,展......
  • PostgreSQL中FIRST_VALUE、LAST_VALUE、LAG 和 LEAD是窗口函数,允许返回在数据集的特
    在PostgreSQL中,FIRST_VALUE、LAST_VALUE、LAG和LEAD是窗口函数(windowfunctions),它们允许你在数据集的特定窗口(或分区)内访问行的相对位置。以下是对这些函数的详细解释和用法:1.FIRST_VALUEFIRST_VALUE函数返回在指定窗口或分区内的第一行的值。它常用于获取每个组的起......
  • 11.10图像增强与动漫化相关依赖
    <?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.or......
  • 在线文件管理器显示乱码或无法删除特定目录
    当您使用在线文件管理器浏览服务器上的文件夹时,如果遇到乱码显示或无法删除特定目录的情况,这通常是由于编码问题、权限不足或文件系统损坏等原因引起的。根据您的描述,这里提供详细的排查步骤和解决方案,帮助您快速解决这些问题:编码问题:确认文件编码:乱码显示往往是因为文件或目......
  • 引用与常量 - 引用类型、const关键字
    引言在C++中,引用和const关键字是两个非常重要的概念。引用提供了一种方便的方式来操作变量的别名,而const关键字则用于定义不可修改的常量或指针。正确理解和使用这两个特性可以提高代码的安全性和可读性。本文将详细介绍引用的基本概念和操作,以及const关键字的各种用法,帮助初......
  • 如何在CentOS服务器上开放特定端口?
    在使用CentOS服务器时,您可能需要开放某些特定的端口以确保应用程序或服务能够正常运行。例如,您可能需要开放843、3000、3001、19923和80等端口,以便这些端口上的服务可以被外部访问。然而,如果您不熟悉Linux防火墙配置,可能会遇到困难。本文将详细介绍如何在CentOS服务器上安全地开放......