2009-07-30 15 views
6

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

अब मैं सिंगलटन पैटर्न व्याप्ति हमेशा की तरह निर्माता निजी myxmlModels बनाने के लिए और myModel का एक उदाहरण वापस जाने के लिए एक स्थिर कारखाने विधि प्रदान करना है का पालन करने के myxmlModel और मॉडल के हर कार्यान्वयन बाध्य करना चाहते हैं कक्षा.लेकिन समस्या इंटरफ़ेस में स्थिर विधि परिभाषाएं नहीं हो सकती हैं और नतीजतन मैं मॉडल के सभी कार्यान्वयन पर किसी विशेष फैक्टरी विधि परिभाषा को लागू नहीं कर सकता। तो एक कार्यान्वयन getObject() प्रदान करने के साथ समाप्त हो सकता है और अन्य न्यूमोडेल() प्राप्त कर सकते हैं।

एक काम के आसपास के myxmlModel के निर्माता पैकेज उपयोग की अनुमति है और एक फैक्टरी वर्ग जो myxmlModel वस्तु बनाता है बना सकते हैं और आगे उपयोग के लिए यह कैश करने के लिए है।

मैं सोच रहा था कि समान कार्यक्षमता प्राप्त करने का एक बेहतर तरीका है या नहीं।

उत्तर

0

क्या आप इंटरफ़ेस को एक अमूर्त वर्ग के रूप में दोबारा कर सकते हैं? यह आपको सभी कार्यान्वयन कक्षाओं के लिए एक विशेष कारखाने विधि को मजबूर करने की अनुमति देगा।

+0

कोशिश की। सार कक्षा – Duleb

+1

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

+0

आह, ज़ाहिर है, इसके बारे में खेद है। – Steven

4
  1. एक ऐसा कारखाना बनाएं जो आपके इंटरफ़ेस, मॉडल के उदाहरण देता है।
  2. मॉडल फैक्ट्री के सभी ठोस कार्यान्वयन-निजी कक्षाएं अपने कारखाने के समान पैकेज में बनाएं।
  3. यदि आपका मॉडल सिंगलटन होना है, और आप जावा 5+ का उपयोग कर रहे हैं, पारंपरिक सिंगलटन के बजाय enum का उपयोग करें, क्योंकि यह सुरक्षित है।
public enum MyXMLModel{ 
INSTANCE(); 
//rest of class 
}; 

संपादित करें: एक और संभावना प्रतिनिधि वर्गों है कि सभी काम कर बनाने और उसके बाद मॉडल विकल्प के सभी प्रदान करने के लिए एक enum का प्रयोग है।

उदाहरण के लिए

:

class MyXMLModelDelegate implements Model { 
public void foo() { /*does foo*/} 
... 
} 

class MyJSONModelDelegate implements Model { 
public void foo() { /*does foo*/ } 
... 
} 

public enum Models { 
XML(new MyXMLModelDelgate()), 
JSON(new MyJSONModelDelegate()); 

private Model delegate; 
public Models(Model delegate) { this.delegate=delegate; } 

public void foo() { delegate.foo(); } 
} 
+0

फैक्टरी ठीक है। लेकिन मैं उत्सुक हूं अगर फैक्टरी के बिना समान कार्यक्षमता हासिल की जा सकती है। – Duleb

+0

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

0

मैं अपने आप को एक ही सवाल पूछने के लिए इस्तेमाल किया। और मैंने एक ही जवाब का प्रस्ताव दिया ;-)

अब मैं आमतौर पर "मजबूर" व्यवहार छोड़ देता हूं, मैं प्रलेखन पर भरोसा करता हूं। मुझे कोई मामला नहीं मिला जहां सिंगलटन पहलू इतना आकर्षक था कि इसे हर तरह से लागू करने की आवश्यकता थी। यह परियोजना के लिए सिर्फ "सर्वोत्तम अभ्यास" है।

मैं आमतौर पर इस तरह की वस्तु, को गति देने के लिए वसंत का उपयोग करता हूं और यह स्प्रिंग कॉन्फ़िगरेशन है जो इसे सिंगलटन बनाता है। सुरक्षित, और इतना आसान ... प्लस इसके अलावा वसंत फायदे (जैसे प्रॉक्सीइंग, कुछ परीक्षण करने के लिए एक बार एक अलग वस्तु को प्रतिस्थापित करना आदि ...)

0

यह केटीएस के उत्तर में आपकी टिप्पणी/स्पष्टीकरण का उत्तर है। क्या ऐसा है कि वास्तविक समस्या सिंगलटन पैटर्न का उपयोग नहीं कर रही है बल्कि इसके बजाय एक ग्रहण (विषुव) विस्तार बिंदु स्कीमा को परिभाषित करने से एक सिंगलटन का योगदान करने की अनुमति मिलती है?

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

जब तक आप विस्तार बिंदु परिभाषा बदल सकते हैं ताकि प्लगइन, एक मॉडल के बजाय एक ModelFactory योगदान की तरह

public interface ModelFactory { 

    public Model getModelInstance(); 

} 

तो विस्तार उपयोगकर्ता एक ModelFactory का दृष्टांत और सिंगलटन प्राप्त करने के लिए यह प्रयोग करेंगे।

यदि मैं गलत अनुमान लगाया, एक टिप्पणी छोड़ और मैं जवाब हटाना;)

+0

हाँ आप सही हैं। लेकिन अगर मैं फैक्ट्री क्लास का पर्दाफाश करता हूं तो अनुबंध (यानी मॉडल इंटरफ़ेस को लागू करने के लिए) विफल हो जाएगा। IConfigurationElement में कई अन्य विधियां हैं जिनका उपयोग हम विस्तार के बारे में अधिक जानकारी प्राप्त करने के लिए कर सकते हैं, शायद कक्षा का नाम प्राप्त करें और ऑब्जेक्ट प्राप्त करने के लिए उस पर एक स्थिर विधि कॉल करें। लेकिन फिर हम एक वर्ग में वापस आते हैं। हम मॉडल इंटरफ़ेस में स्थिर घोषणा नहीं कर सकते हैं। – Duleb

+0

बिल्कुल नहीं - अनुबंध सिर्फ मॉडल फैक्टरी वर्ग में स्थानांतरित हो गया है। अब आपके पास दो अनुबंध होंगे: कारखाना (विस्तार बिंदु के माध्यम से योगदान) और मॉडल (फैक्ट्री को मॉडल कार्यान्वयन वापस करना होगा) –

2

आप प्रतिबिंब का उपयोग कर सकते हैं। कुछ इस तरह:

public interface Model { 
    class Singleton { 
    public static Model instance(Class<? extends Model> modelClass) { 
     try { 
     return (Model)modelClass.getField("instance").get(null); 
    } catch (blah-blah) { 
     blah-blah 
    } 
    } 
} 

public class XmlModel implements Model { 
    private static final Model instance = new XmlModel(); 

    private XmlModel() { 
    } 
} 

उपयोग:

Model.Singleton.instance(XmlModel.class) 

वास्तव में, मैं बहुत इस कोड को पसंद नहीं है :)। सबसे पहले, यह प्रतिबिंब का उपयोग करता है - बहुत धीमा, दूसरा - कक्षाओं की गलत परिभाषाओं के मामले में रनटाइम त्रुटियों की संभावनाएं हैं।

+0

मुझे लगता है कि प्रतिबिंब काम करेगा। – Duleb

संबंधित मुद्दे