一次性加载的配置属性的设计模式?[已关闭]

2022-09-01 04:35:52

我经常遇到在内存中存储从文件系统上的文件加载的一些(可能很复杂的)配置设置的问题。但是,我想知道是否有比我一直在使用的更好的方法来构建这个问题的模式。

从本质上讲,我目前的解决方案涉及三个步骤。

  1. 构建单例。由于数据是持久的,并且保证不会在应用程序的运行时中更改,因此只需要一个对象实例。

  2. 当对对象发出第一个请求时,创建该对象并从文件中读入。

  3. 使用 getter 公开数据。

这样做的效果是,我的很多代码都是这样的:,这对我来说看起来很奇怪。MyConfiguration.getInstance().getWeightOfBomb()

有没有更好的方法以更语义的方式处理这个问题?


答案 1

依赖注入。你不一定要使用像SpringGuice这样的DI框架,但你真的想避免用单例来散布你的代码。您仍然可以在实现中使用单例,但没有理由需要您的代码的其余部分知道它是单例。在单元测试和重构时,单例是巨大的痛苦。让代码改为引用接口。例如,

 interface MyConfig {
     double getWeightOfBomb();
 }

 class SomeClass {
    private MyConfig myConfig;

    public void doSomething() {
       myConfig.getWeightOfBomb();
    }
 }

 class MyConfigImpl implements MyConfig {
     public double getWeightOfBomb() {           
          return MyConfiguration.getInstance().getWeightOfBomb(); 
     }
 }

如果使用 DI 框架,只需设置类即可注入实现。如果你不这样做,那么最懒惰的方法仍然具有所有的好处,就是做这样的事情:MyConfig

 class SomeClass {
    private MyConfig myConfig = new MyConfigImpl();        
 }

真的这取决于你。重要的是,当您以后意识到需要改变行为和/或进行单元测试时,您可以按实例进行替换。myConfig


答案 2

您可以创建一个接口来表示配置:

public interface Config {
    interface Key {}
    String get(Key key);
    String get(Key key, String defaultValue);
}

和单例实现:

public enum MyConfig implements Config {
    INSTANCE("/config.properties");
    private final Properties config;

    MyConfig(String path) {
        config = new Properties();
        try {
            config.load(this.getClass().getResourceAsStream(path));
        } catch (IOException | NullPointerException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    @Override
    public String get(Config.Key key){
        return config.getProperty(key.toString());
    }

    @Override
    public String get(Config.Key key, String defaultValue) {
        return config.getProperty(key.toString(), defaultValue);
    }

    public enum Key implements Config.Key {
        PROXY_HOST("proxy.host"),
        PROXY_PORT("proxy.port");
        private final String name;

        Key(String name) { this.name = name; }    
        @Override
        public String toString() { return name; }
    }
}

然后在您的类中注入配置:

public class SomeClass  {
    private final Config config;

    public SomeClass(Config config) {
        this.config = config;
    }

    public void someMethod() {
        String host = config.get(Key.PROXY_HOST);
        String port = config.get(Key.PROXY_PORT, "8080");
        // Do something
    }
}

推荐