Estoy a menudo se enfrentan con el problema de almacenar, en la memoria, un par de (posiblemente complejas) configuración de los ajustes de carga de archivos en el sistema de archivos. Me pregunto si hay una manera mejor de arquitecto de un patrón de este problema, sin embargo, que lo he estado usando.

Esencialmente, mi solución actual consta de tres pasos.

  1. Construir un singleton. Ya que los datos son persistentes y con la garantía de no cambiar a través del tiempo de ejecución de la aplicación, sólo una instancia de objeto deben de ser necesario.

  2. Cuando la primera solicitud para el objeto, crear el objeto y leer desde un archivo.

  3. Exponer datos con captadores.

Esto tiene el efecto de que una gran parte de mi código es este:
MyConfiguration.getInstance().getWeightOfBomb(), que tiene un aspecto bastante extraño para mí.

Existe una mejor manera de manejar esto de una forma más semántica de la moda?

3 Comentarios

  1. 34

    La Inyección De Dependencia. Usted no necesariamente tiene que utilizar un DI marco como La primavera o Guice pero usted realmente desea evitar ensuciar el código con los embarazos únicos. Usted puede todavía utilizar un singleton en la aplicación, pero no hay ninguna razón el resto de su código debe saber que es un singleton. Los únicos son enormes dolor cuando la unidad de pruebas y refactorización. Deje que su código de referencia de una interfaz en su lugar. por ejemplo,

     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(); 
         }
     }

    Si utiliza un DI marco, sólo la configuración de las clases para tener su MyConfig aplicación inyectada. Si no, entonces el más perezoso enfoque que todavía tiene todos los beneficios es hacer algo como:

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

    Realmente depende de usted. Lo importante es que usted puede reemplazar myConfig por ejemplo cuando usted más tarde darse cuenta de que necesita el comportamiento para variar y/o para pruebas de unidad.

    • Un montón de veces, solo me falta poner algo de propiedades de configuración en la consola de small apps (que he estado escribiendo en masa, últimamente). En aplicaciones grandes, aunque (para el que he adoptado este patrón), este método funciona bien.
  2. 4

    Podría crear una interfaz para representar la configuración:

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

    Y una sola aplicación:

    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; }
        }
    }

    Y, a continuación, inyectar la configuración en sus clases:

    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
        }
    }
  3. 2

    Adicional propuesta de noé respuesta.

    Si es inconveniente para que usted escriba un método para cada parámetro de configuración, entonces usted podría utilizar enum para que. Aquí es lo que quiero decir:

    public class Configuration {
    
    private final Properties properties;
    
    public enum Parameter {
        MY_PARAMETER1("my.parameter1", "value1"),
        MY_PARAMETER2("my.parameter2", "value2");
    
        private final String name;
        private final String defaultValue;
    
        private Parameter(String name, String defaultValue) {
            this.name = name;
            this.defaultValue = defaultValue;
        }
    
        private String getName() {
            return name;
        }
    
        private String getDefaultValue() {
            return defaultValue;
        }
    }
    
    
    public Configuration(Properties properties) {
        this.properties = (Properties)properties.clone();
    }
    
    //single method for every configuration parameter
    public String get(Parameter param) {
        return properties.getProperty(param.getName(), param.getDefaultValue());
    }

    }

    Después de eso, si usted tiene un nuevo parámetro de configuración, todo lo que necesita hacer es agregar una nueva enumeración de entrada.

    También puede extraer una interfaz de Configuración de la clase, por supuesto, moviendo enum fuera.

Dejar respuesta

Please enter your comment!
Please enter your name here