2010-03-23 9 views
30

मुझे अक्सर फाइल सिस्टम पर फ़ाइलों से लोड की गई कुछ (संभावित रूप से जटिल) विन्यास सेटिंग्स, स्मृति में भंडारण की समस्या का सामना करना पड़ता है। मैं सोच रहा हूं कि इस समस्या के पैटर्न को आर्किटेक्ट करने का बेहतर तरीका है, हालांकि, जो मैं उपयोग कर रहा हूं उससे।एक बार लोड विन्यास गुणों के लिए डिजाइन पैटर्न?

अनिवार्य रूप से, मेरे वर्तमान समाधान में तीन कदम शामिल हैं।

  1. एक सिंगलटन बनाएं। चूंकि डेटा लगातार और गारंटीकृत है कि एप्लिकेशन के रनटाइम के माध्यम से नहीं बदला जाए, केवल एक ऑब्जेक्ट इंस्टेंस की आवश्यकता होनी चाहिए।

  2. जब ऑब्जेक्ट के लिए पहला अनुरोध किया गया है, तो ऑब्जेक्ट बनाएं और फ़ाइल से पढ़ें।

  3. गेटर्स के साथ डेटा का खुलासा करें। MyConfiguration.getInstance().getWeightOfBomb(), जो मेरे लिए नहीं बल्कि अजीब लग रहा है:

इस आशय यह है कि मेरे कोड का एक बहुत कुछ इस तरह लग रहा है है।

क्या यह एक और अधिक अर्थपूर्ण फैशन में इसे संभालने का एक बेहतर तरीका है?

उत्तर

29

निर्भरता इंजेक्शन। आपको Spring या Guice जैसे डीआई फ्रेमवर्क का उपयोग करने की आवश्यकता नहीं है, लेकिन आप वास्तव में सिंगलटन के साथ अपने कोड को कूड़ेदान से बचना चाहते हैं। आप अभी भी कार्यान्वयन में एक सिंगलटन का उपयोग कर सकते हैं, लेकिन आपके शेष कोड को यह जानने की कोई आवश्यकता नहीं है कि यह एक सिंगलटन है। यूनिट परीक्षण और रिफैक्टरिंग करते समय सिंगलेटन बहुत दर्द होता है। अपने कोड को इसके बजाय एक इंटरफ़ेस संदर्भित करने दें। उदाहरण के लिए,

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

आप एक डि ढांचे का उपयोग करते हैं, सेटअप आप कक्षाएं अपने MyConfig कार्यान्वयन इंजेक्शन है।

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

वास्तव में यह आप पर निर्भर है: यदि आप नहीं करते हैं, तो laziest दृष्टिकोण अभी भी सभी लाभ है कि ऐसा कुछ करने के लिए है। महत्वपूर्ण बात यह है कि आप प्रति उदाहरण आधार पर myConfig को प्रतिस्थापित कर सकते हैं जब आप बाद में महसूस करते हैं कि आपको अलग-अलग व्यवहार और/या यूनिट परीक्षण के लिए व्यवहार की आवश्यकता है।

+3

एक बहुत कई बार, मुझे बस छोटे कंसोल ऐप्स में कुछ कॉन्फ़िगरेशन गुणों को लपेटने की आवश्यकता होती है (जिसे मैं हाल ही में लिख रहा हूं) । बड़े अनुप्रयोगों में, हालांकि (जिसके लिए मैंने इस पैटर्न को अपनाया है), यह विधि अच्छी तरह से काम करती है। –

2

नोहा के उत्तर के लिए अतिरिक्त प्रस्ताव।

यदि प्रत्येक कॉन्फ़िगरेशन पैरामीटर के लिए कोई विधि लिखना आपके लिए असुविधाजनक है, तो आप इसके लिए enum का उपयोग कर सकते हैं।

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

}

उसके बाद, यदि आप एक नया विन्यास पैरामीटर है, तुम सब करने की जरूरत है एक नया enum प्रविष्टि जोड़ने के लिए है: यहाँ मैं क्या मतलब है।

आप निश्चित रूप से कॉन्फ़िगरेशन क्लास से एक इंटरफ़ेस निकाल सकते हैं, ज़ाहिर है, बाहर enum चल रहा है।

3

आप एक इंटरफेस बना सकते हैं विन्यास का प्रतिनिधित्व करने के:

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 
    } 
} 
संबंधित मुद्दे