2013-02-19 10 views
5

के साथ सिंगलटन क्लास मैं कंप्यूटर दृष्टि अनुप्रयोग विकसित कर रहा हूं और मुझे क्लासिफायर क्लास की आवश्यकता होगी। यह कक्षा आवेदन के प्रति रन अपरिवर्तनीय होगी और यह शुरुआतीकरण पर डिस्क से प्रशिक्षित डेटा लोड करती है। मैं यह सुनिश्चित करना चाहता हूं कि पूरे कार्यक्रम में एक ही प्रशिक्षित डेटा तक पहुंच होगी और मैं लोड होने के बाद डिस्क से पुनः लोड करना चाहता हूं।पैरामीटर

जो मैं विचार कर रहा था वह स्थिर वर्ग या सिंगलटन का उपयोग करना था। मुझे यकीन नहीं है कि डेटा को स्थिर वर्ग में कैसे लोड किया जाए, क्योंकि डेटा फ़ाइल का पथ संकलन समय पर नहीं जानता है - यह प्रोग्राम तर्क होगा। तो मैं सिंगलटन पैटर्न के बारे में सोच रहा था, लेकिन वहां मुझे नहीं पता कि इसे गतिशील रूप से कैसे प्रारंभ किया जाए।

class Singleton { 
    private static Singleton instance; 
    private Singleton() { ... } 
    private static SomeDataObject data; 

    public static Singleton getInstance() { 
     if(instance == null) 
      instance = new Singleton(); 

      return instance; 
    } 

    public static init(string dataPath){ 
     if(data == null) 
      loadDataFromFile(dataPath) 
    } 
} 

यह कार्य नहीं करेगा, क्योंकि मैं कोई नियंत्रण नहीं है जो विधि पहले बुलाया जाएगा है:

मेरा विचार निम्नलिखित इस्तेमाल किया गया।

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

रनटाइम पर सिंगलटन को प्रारंभ करने के तरीके में संक्षेप में कैसे?

+0

कार्यक्रम तर्क 'डेटापाथ' प्रोग्रामेटिक रूप से सुलभ कैसे है? –

+0

आपको *** दोनों *** एक स्थिर सिंगलटन उदाहरण *** और *** डेटा ऑब्जेक्ट की आवश्यकता नहीं है। इसके अलावा, आपका वर्तमान सिंगलटन कार्यान्वयन थ्रेड सुरक्षित नहीं है। – Perception

+0

@MattBall यह या तो GUI से हो सकता है, या कमांड लाइन तर्क – jnovacho

उत्तर

8

मुझे नहीं लगता (बिल्कुल) जो आप करना चाहते हैं वह काम करेगा।

नीचे काम करेगा:

public static void main(String[] args) 
{ 
    Singleton.init("somepath"); 
    ... 
    Singleton.getInstance().doingStuff(); 
    ... 
} 

इससे बेहतर कार्यान्वयन हो सकता है: (जो एक NullPointerException कारण यदि आप init पहले बुला बिना इसका इस्तेमाल करने की कोशिश करेंगे) (वास्तव में नहीं सिंगलटन किसी भी अधिक है, हालांकि)

private static Singleton instance; 
private SomeDataObject data; 

private Singleton(String path) { loadDataFromFile(path); ... } 

public static Singleton getInstance() { 
    return instance; 
} 

public static void init(String dataPath){ 
    instance = new Singleton(dataPath); 
} 

तो फिर वहाँ है: (संभव बुरा कोडिंग अभ्यास एक तरफ)

class Main 
{ 
    public static void main(String[] args) 
    { 
    Singleton.currentPath = "somepath"; 
    ... 
    } 
} 

class Singleton 
{ 
    public static String currentPath = null; 
    private static Singleton instance; 
    private SomeDataObject data; 

    private Singleton(String path) { loadDataFromFile(path); ... } 

    public static Singleton getInstance() { 
    if(instance == null && currentPath != null) 
     instance = new Singleton(currentPath); 
    return instance; 
    } 
} 

जो मुझे लगता है वास्तव में ज्यादा हल नहीं करता है।

+0

लेकिन मैं सिंगलटन.getInstance()। DoStuff() और यह त्रुटि होगी, क्योंकि कोई प्रारंभिकरण नहीं है किया गया। जैसा कि मैंने अपनी पोस्ट में कहा है, मेरे कोड में मैं इसका ट्रैक रख सकता हूं, लेकिन आम तौर पर यह कुछ भी हल नहीं करता है। – jnovacho

+0

@jnovacho आप कन्स्ट्रक्टर कहीं और संग्रहीत एक स्थिर चर पढ़ सकते हैं, लेकिन मुझे लगता है कि यह मूल रूप से एक ही समस्या है। मुझे नहीं लगता कि आप उत्तर में जो कुछ भी प्रदान करते हैं उससे बेहतर कर सकते हैं (जब तक आप प्रत्येक कॉल पर पथ प्राप्त करने के लिए 'getInstance') पास नहीं करना चाहते हैं। – Dukeling

+0

मेरे लिए पहले व्यक्ति ने सार्वजनिक स्थैतिक शून्य init() के साथ काम किया –

0

मैं कुछ ऐसे सिंक्रनाइज़ किए गए समाधान के साथ वर्तमान जीतने वाले समाधान की तुलना में "अधिक" थ्रेडसेफ का उपयोग करता हूं।

import java.util.function.Supplier; 

public class InitOnce { 

/** 
* Marked as final to prevent JIT reordering 
*/ 
private final Supplier<String> theArgs; 

private InitOnce(Supplier<String> supplier) { 
    super(); 
    this.theArgs = supplier; 
} 

/** 
* Uses the arguments to do something 
* 
* @return 
*/ 
public String doSomething() { 
    return "Something : " + theArgs.get(); 
} 

/** 
* Initializes all the things 
* 
* @param someArgs 
*/ 
public static synchronized void init(final Supplier<String> someArgs) { 
    class InitOnceFactory implements Supplier<InitOnce> { 
     private final InitOnce initOnceInstance = new InitOnce(someArgs); 

     @Override 
     public InitOnce get() { 
      return initOnceInstance; 
     } 
    } 

    if (!InitOnceFactory.class.isInstance(instance)) { 
     instance = new InitOnceFactory(); 
    } else { 
     throw new IllegalStateException("Already Initialized"); 
    } 
} 

private static Supplier<InitOnce> instance = new InitOnceHolder(); 

/** 
* Temp Placeholder supplier 
* 
*/ 
private static final class InitOnceHolder implements Supplier<InitOnce> { 
    @Override 
    public synchronized InitOnce get() { 

     if (InitOnceHolder.class.isInstance(instance)) 
      throw new IllegalStateException("Not Initialized"); 

     return instance.get(); 
    } 

} 

/** 
* Returns the instance 
* 
* @return 
*/ 
public static final InitOnce getInstance() { 
    return instance.get(); 
} 
}