java - 枚举中的可配置值

标签 java configuration enums extend

我经常在我的代码中使用这种设计来维护可配置的值。考虑这段代码:

public enum Options {

    REGEX_STRING("Some Regex"),
    REGEX_PATTERN(Pattern.compile(REGEX_STRING.getString()), false),
    THREAD_COUNT(2),
    OPTIONS_PATH("options.config", false),
    DEBUG(true),
    ALWAYS_SAVE_OPTIONS(true),
    THREAD_WAIT_MILLIS(1000);

    Object value;
    boolean saveValue = true;

    private Options(Object value) {
        this.value = value;
    }

    private Options(Object value, boolean saveValue) {
        this.value = value;
        this.saveValue = saveValue;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public Object getValue() {
        return value;
    }

    public String getString() {
        return value.toString();
    }

    public boolean getBoolean() {
        Boolean booleanValue = (value instanceof Boolean) ? (Boolean) value : null;
        if (value == null) {
            try {
                booleanValue = Boolean.valueOf(value.toString());
            }
            catch (Throwable t) {
            }
        }

        // We want a NullPointerException here
        return booleanValue.booleanValue();
    }

    public int getInteger() {
        Integer integerValue = (value instanceof Number) ? ((Number) value).intValue() : null;
        if (integerValue == null) {
            try {
                integerValue = Integer.valueOf(value.toString());
            }
            catch (Throwable t) {
            }
        }
        return integerValue.intValue();
    }

    public float getFloat() {
        Float floatValue = (value instanceof Number) ? ((Number) value).floatValue() : null;
        if (floatValue == null) {
            try {
                floatValue = Float.valueOf(value.toString());
            }
            catch (Throwable t) {
            }
        }
        return floatValue.floatValue();
    }

    public static void saveToFile(String path) throws IOException {
        FileWriter fw = new FileWriter(path);
        Properties properties = new Properties();
        for (Options option : Options.values()) {
            if (option.saveValue) {
                properties.setProperty(option.name(), option.getString());
            }
        }
        if (DEBUG.getBoolean()) {
            properties.list(System.out);
        }
        properties.store(fw, null);
    }

    public static void loadFromFile(String path) throws IOException {
        FileReader fr = new FileReader(path);
        Properties properties = new Properties();
        properties.load(fr);

        if (DEBUG.getBoolean()) {
            properties.list(System.out);
        }
        Object value = null;
        for (Options option : Options.values()) {
            if (option.saveValue) {
                Class<?> clazz = option.value.getClass();
                try {
                    if (String.class.equals(clazz)) {
                        value = properties.getProperty(option.name());
                    }
                    else {
                        value = clazz.getConstructor(String.class).newInstance(properties.getProperty(option.name()));
                    }
                }
                catch (NoSuchMethodException ex) {
                    Debug.log(ex);
                }
                catch (InstantiationException ex) {
                    Debug.log(ex);
                }
                catch (IllegalAccessException ex) {
                    Debug.log(ex);
                }
                catch (IllegalArgumentException ex) {
                    Debug.log(ex);
                }
                catch (InvocationTargetException ex) {
                    Debug.log(ex);
                }

                if (value != null) {
                    option.setValue(value);
                }
            }
        }
    }
}

这样,我就可以轻松地从文件中保存和检索值。问题是我不想到处重复这段代码。正如我们所知,枚举不能扩展;所以无论我在哪里使用它,我都必须将所有这些方法放在那里。我只想声明这些值以及它们是否应该保留。每次都没有方法定义;有什么想法吗?

最佳答案

像这样使用enum 来保存可配置的值看起来是一个完全错误的设计。枚举是单例,因此实际上您在任何给定时间只能激活一个配置。

EnumMap 听起来更像您所需要的。它在 enum 外部,因此您可以根据需要实例化任意数量的配置。

import java.util.*;
public class EnumMapExample {
    static enum Options {
        DEBUG, ALWAYS_SAVE, THREAD_COUNT;
    }
    public static void main(String[] args) {
        Map<Options,Object> normalConfig = new EnumMap<Options,Object>(Options.class);
        normalConfig.put(Options.DEBUG, false);
        normalConfig.put(Options.THREAD_COUNT, 3);
        System.out.println(normalConfig);
        // prints "{DEBUG=false, THREAD_COUNT=3}"

        Map<Options,Object> debugConfig = new EnumMap<Options,Object>(Options.class);
        debugConfig.put(Options.DEBUG, true);
        debugConfig.put(Options.THREAD_COUNT, 666);
        System.out.println(debugConfig);
        // prints "{DEBUG=true, THREAD_COUNT=666}"  
    }
}

API 链接

  • java.util.EnumMap

    A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum maps are represented internally as arrays. This representation is extremely compact and efficient.

关于java - 枚举中的可配置值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2902113/

相关文章:

java - 如何处理GXT 2.2网格中单元格的点击?

symfony - 如何在 nginx 的子目录中安装 symfony2 应用程序

java - 如何为 Java 6 枚举实现 values()?

java - 大型浮点文字的舍入模式是否明确规定?

java - 使用 charAt() 而不使用compareTo() 方法按字典顺序比较两个字符串

java - Bukkit/Spigot API : Mapping damager and Victim

java - 更改 hibernate.cfg.xml 运行时 - 第一部分

docker - 如何启用实验性 Docker CLI 功能

java - 为什么我不能在 Kotlin 中访问父类(super class)的枚举?

c++ - 尝试在 C++ Visual Studio 2010 中声明枚举时出现奇怪错误