枚举类型在游戏中实战应用

来源:互联网 发布:云南省建设厅官网通知 编辑:程序博客网 时间:2024/06/06 02:28

一)枚举类型简介

枚举是一种特殊的数据类型,和类(class)是同一个级别,例如定义一个类Test,会有一个源文件Test.java,编译会有一个字节码Test.class,那么定义一个枚举类型Myenum,编译也会产生Myenum.class。
作用:存储了一系列数据,保证数据的一个有效取值。
通常用到的地方是传递接口参数的时候,为了保证能传递一个合适的值,而不需要验证这个值是否合法,那么接口参数可以设置为枚举类型,这里说的接口不是interface,而是只针对开发的不同层之间调用。

二)简单应用

    枚举类型在实际使用过程中往往会统一在一个类中单独管理,极少在类内部单独建立一个枚举类型,以下为测试

/** * * @author xiu * @version 2017年8月3日 下午2:46:25  */public enum Color {RED,GREEN,BLACK,YELLOW,WHITE;}
这是最简单的枚举类型定义,使用也可以结合switch,结合switch在实际开发中也很常用
/** * * @author xiu * @version 2017年8月3日 下午2:50:19  */public class Signal {enum Color {        GREEN, YELLOW, RED    }public class TrafficLight {Color color = Color.RED;        public void change() {            switch (color) {            case RED:                color = Color.GREEN;                break;            case YELLOW:                color = Color.RED;                break;            case GREEN:                color = Color.YELLOW;                break;            }        }}}

三)扩展应用

1)简单拓展

            通过括号赋值,而且必须有带参构造器和一属性跟方法,否则编译出错;

        赋值必须是都赋值或都不赋值,不能一部分赋值一部分不赋值;

        如果不赋值则不能写构造器,赋值编译也出错。

        这种方式主要是解决实际开发过程中有些参数状态的定义值的获取,例如Color枚举类型要获得对应的枚举类型所在位置参数值value,如果按照上面的设计可以通过GameStatus.OVERGAME.ordinal()方式获取该参数所在位置索引,位置索引在实际开发过程中使用较为频繁,只是如果这个参数值要求很大这种方式就不适用。

/** *游戏状态定义 * * @author xiu * @version 2017年8月3日 下午2:58:59  */public class GameStatusDefs { // 游戏状态    public enum GameStatus {        PREPARE(1), // 准备状态        RUNNING(2), // 运行状态        ENDGAME(3),//当前牌局结束        OVERGAME(4);// 结束状态                private final int value;        GameStatus(int value) {            this.value = value;        }        public int getValue() {            return value;        }    }}
通过这种方式可以定义游戏的类型状态,同时可以通过getValue()方法获得参数后面的括号内的参数值

/** *枚举类型简单实例 * * @author xiu * @version 2017年8月3日 下午3:09:50  */public class testEnum {enum Color {RED,//0GREEN,//1BLACK,//2YELLOW,//3WHITE;//4} // 游戏状态    public enum GameStatus {        PREPARE(1), // 准备状态        RUNNING(2), // 运行状态        ENDGAME(3),//当前牌局结束        OVERGAME(4);// 结束状态                private final int value;        GameStatus(int value) {            this.value = value;        }        public int getValue() {            return value;        }    }public static void main(String[] args) {int value = 0;value = Color.BLACK.ordinal();System.out.println("普通枚举类型用法,常量所在位置:" + value);value = GameStatus.OVERGAME.ordinal();System.out.println("扩展用法,常量所在位置:" +value);value = GameStatus.RUNNING.getValue();System.out.println("扩展用法,常量对应参数:" +value);}}
输出结果:

普通枚举类型用法,常量所在位置:2常量所在位置:3常量对应参数:2


2)深层拓展

       对于一个枚举类型既要获取其名字含义还要获得对应的参数值

/** * * @author xiu * @version 2017年8月3日 下午2:46:25  */public enum Color {        RED("红色", 1),        GREEN("绿色", 2),        BLANK("白色", 3),         YELLO("黄色", 4);        // 成员变量        private String name;        private int index;        // 构造方法        private Color(String name, int index) {            this.name = name;            this.index = index;        }        // 普通方法        public static String getName(int index) {            for (Color c : Color.values()) {                if (c.getIndex() == index) {                    return c.name;                }            }            return null;        }        // get set 方法        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public int getIndex() {            return index;        }        public void setIndex(int index) {            this.index = index;        }    }

测试

/** * @author xiu * @version 2017年8月3日 下午3:31:39  */public class testColor {public static void main(String[] args) {System.out.println("扩展枚举类型对象:" + Color.RED);System.out.println("扩展枚举类型索引:" + Color.RED.getIndex());System.out.println("扩展枚举类型对象名字:" + Color.RED.getName());}}结果:扩展枚举类型对象:RED扩展枚举类型索引:1扩展枚举类型对象名字:红色

在实际开发过程中枚举类型的使用主要是结合switch使用和简单拓展使用,深层拓展在一些特殊用法中使用。

四)枚举类型与常量的使用区别

1)先看代码

package com.xiu.enums;/** *游戏状态定义 * * @author xiu * @version 2017年8月3日 下午2:58:59  */public class GameStatusDefs {/**准备状态*/public static final int PREPARE = 1;/**运行状态*/public static final int RUNNING = 10;/**当前局结束*/public static final int ENDGAME = 20;/**退出状态*/public static final int OVERGAME = 30;// 游戏状态枚举类型    public enum GameStatus {        PREPARE(1), // 准备状态        RUNNING(2), // 运行状态        ENDGAME(3),//结束        OVERGAME(4);// 退出状态                private final int value;        GameStatus(int value) {            this.value = value;        }        public int getValue() {            return value;        }    }        public static voidmain(String[] args) {System.err.println("游戏退出状态 常量:" + OVERGAME);System.err.println("游戏退出状态 枚举类型 索引:" + GameStatus.OVERGAME.ordinal());System.err.println("游戏退出状态 枚举类型 参数:" + GameStatus.OVERGAME.getValue());}}结果:游戏退出状态 常量:30游戏退出状态 枚举类型 索引:3游戏退出状态 枚举类型 参数:4

参考意见:

使用常量定义方式有什么不好了,大家都这样用了很长时间了,没什么问题啊?

1.首先,它不是类型安全的。你必须确保是int

     其次,你还要确保它的范围是0和1

     最后,很多时候你打印出来的时候,你只看到 1 和0 ,但其没有看到代码的人并不知道你的企图,抛弃你所有旧的public static final常量 

2. 可以创建一个enum类,把它看做一个普通的类。除了它不能继承其他类了。(java是单继承,它已经继承了Enum), 可以添加其他方法,覆盖它本身的方法

3. switch()参数可以使用enum了

4. values()方法是编译器插入到enum定义中的static方法,所以,当你将enum实例向上转型为父类Enum是,values()就不可访问了。解决办法:在Class中有一个getEnumConstants()方法,所以即便Enum接口中没有values()方法,我们仍然可以通过Class对象取得所有的enum实例

5. 无法从enum继承子类,如果需要扩展enum中的元素,在一个接口的内部,创建实现该接口的枚举,以此将元素进行分组。达到将枚举元素进行分组。

6. 使用EnumSet代替标志。enum要求其成员都是唯一的,但是enum中不能删除添加元素。

7. EnumMap的key是enum,value是任何其他Object对象。

8. enum允许程序员为eunm实例编写方法。所以可以为每个enum实例赋予各自不同的行为。

9. 使用enum的职责链(Chain of Responsibility) .这个关系到设计模式的职责链模式。以多种不同的方法来解决一个问题。然后将他们链接在一起。当一个请求到来时,遍历这个链,直到链中的某个解决方案能够处理该请求。

10. 使用enum的状态机

11. 使用enum多路分发


实际开发中也没有这么多的区别,根据实际需要使用,并不需要拘谨于一砖一瓦。
更多拓展参考:http://blog.csdn.net/wgw335363240/article/details/6359614

http://developer.51cto.com/art/201107/275031.htm