一次性加载配置属性的设计模式?

Ste*_*all 34 java configuration design-patterns

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

基本上,我目前的解决方案涉及三个步骤.

  1. 建立一个单身人士.由于数据是持久的并且保证不会通过应用程序的运行时更改,因此只需要一个对象实例.

  2. 完成对对象的第一次请求后,创建对象并从文件读入.

  3. 用getter公开数据.

这有很多我的代码看起来像这样的效果: MyConfiguration.getInstance().getWeightOfBomb()对我来说这看起来很奇怪.

是否有更好的方式以更加语义的方式处理这个问题?

noa*_*oah 34

依赖注入.您不一定要使用像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(); 
     }
 }
Run Code Online (Sandbox Code Playgroud)

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

 class SomeClass {
    private MyConfig myConfig = new MyConfigImpl();        
 }
Run Code Online (Sandbox Code Playgroud)

真的,这取决于你.重要的是,myConfig当您稍后意识到需要改变行为和/或进行单元测试时,您可以在每个实例的基础上进行替换.

  • 很多时候,我只需要在小型控制台应用程序中包装一些配置属性(我最近一直在集体编写).但是在较大的应用程序中(我采用了这种模式),这种方法效果很好. (3认同)

alb*_*bur 6

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

public interface Config {
    interface Key {}
    String get(Key key);
    String get(Key key, String defaultValue);
}
Run Code Online (Sandbox Code Playgroud)

还有一个单例实现:

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)