एक DAO सिंगलटन होना चाहिए या नहीं?


14

मैं एक RESTful API विकसित कर रहा हूं और मुझे लगता है कि मेरे संसाधनों के लिए DAO का उपयोग करना सुविधाजनक है क्योंकि यद्यपि मैं उन्हें स्टोर करने के लिए मेमोरी का उपयोग करने की योजना बना रहा हूं, लेकिन मैं अपने पुस्तकालय का उपयोग करने के लिए कोई दरवाजा बंद नहीं करना चाहता हूं यदि उन्होंने उपयोग करने का निर्णय लिया है डीएओ के लिए एक डेटाबेस कार्यान्वयन।

मेरा सवाल यह है कि क्या डीएओ एकल होना चाहिए या नहीं। यदि यह नहीं है, तो सेवा में DAO का एक उदाहरण होगा और यह मोटे तौर पर इस तरह दिखेगा:

@Path("eventscheduler")
public class EventSchedulerService {
    private IEventSchedulerDao dao = new EventSchedulerDao();

    // in case a different implementation is to be used
    public void setEventSchedulerDao(IEventSchedulerDao dao) {
        this.dao = dao;
    }

    @Path("{uniqueName}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Tournament getTournament(@PathParam("name") String uniqueName) {
        return dao.get(uniqueName);
    }

    @Path("create")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Tournament createTournament(Tournament tournament) {
        return dao.create(tournament);
    }
}

हालांकि अगर DAO एक सिंगलटन था, लेकिन मुझे लगता है कि इसमें बहुत अंतर नहीं होगा, बस पहली पंक्ति में:

private IEventSchedulerDao dao = EventSchedulerDao.getInstance();

मुझे अभी भी एक IEventSchedulerDaoउदाहरण का उपयोग करना होगा , लेकिन मुझे लगता है कि सभी एकल इस तरह से काम करते हैं? किसी कारण से मैं हमेशा एकल विधियों को स्थैतिक तरीकों से सहसंबंधित करता हूं, इसलिए उपयोगकर्ता के साथ दिखाई देने वाले एक सिंगलटन उदाहरण के बजाय getInstance(), यह छिपा होगा और वह EventSchedulerDao.get(name)एक स्थिर शैली में आदि का उपयोग करेगा । यह कोई बात है या यह सिर्फ मैं हूं?

तो, क्या मुझे सिंगलटन डीएओ नहीं होना चाहिए या नहीं?

और एक पक्ष के प्रश्न के रूप में, क्या यह सही है कि उपयोगकर्ता के लिए अपने स्वयं के DAO को लागू करने के लिए खुले दरवाजे हैं?


आप एक स्थिर एक्सेसर के साथ एक सिंगलटन के बजाय IoC सिंगलटन का उपयोग कर सकते हैं।
कोडइन्चोस 12

जवाबों:


10

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


1
आप अपने अंतिम वाक्य में जो सुझाव देते हैं वह ठीक वही है जो मैं सही कर रहा हूं?
11

1
आप एक इंटरफ़ेस (हाँ) के माध्यम से संदर्भित कर रहे हैं, लेकिन आप DAO को इंजेक्ट नहीं कर रहे हैं (स्पष्ट होने के लिए ....)
ब्रायन एग्न्यू

क्या मतलब? मेरे पास इसके लिए एक सेटर है, क्या मैं नहीं?
दादाबा

@dabadaba लाइन private IEventSchedulerDao dao = new EventSchedulerDao();वह जगह है जहाँ आप गलत हो गए हैं। IEventSchedulerDaoनिर्माण के लिए कार्यान्वयन को इंजेक्शन के माध्यम से किया जाना चाहिए और कभी नहीं बदला (यानी, बहुत छुटकारा पाएं setEventSchedulerDao)।
डेविड अरनो

ठीक है मैं समझ गया। मैंने सिर्फ एक डिफ़ॉल्ट डीएओ प्रदान करने के लिए ऐसा किया है और इसे बदलना "वैकल्पिक" होगा। लेकिन आपके सुझाव को लेने का अर्थ है कि डिफ़ॉल्ट से अलग सेवा के लिए एक कंस्ट्रक्टर होना, और शायद ही मुझे इस बात का कोई अंदाजा नहीं है कि यह जर्सी के साथ कैसे काम करता है क्योंकि यह डिफ़ॉल्ट कंस्ट्रक्टर का उपयोग करता है। किसी भी तरह से आप जानते हैं कि कैसे करना है?
dabadaba

4

A D ata A ccess O bject केवल आपके एप्लिकेशन में एक बार मौजूद होना चाहिए। तर्क एक ही रहता है, केवल चीजें जो भिन्न हैं वे डीएओ द्वारा प्रदान की जाने वाली विधियों में आने वाले और बाहर के मूल्य हैं।

इस बात को ध्यान में रखते हुए, जाहिर तौर पर पहली बात यह है कि आमतौर पर डीएओ को एक मजबूत सिंगलटन के रूप में लागू किया जाता है , यानी जब आपके पास staticएक कारखाना वर्ग होता है, तो कुछ ऐसा होता है getInstance, आलसी डीएओ के एक उदाहरण को लोड करता है यदि यह अशक्त है और इसे वापस कर रहा है।

मुझे माफ करना अगर वाक्य रचना पूरी तरह से सही नहीं है, तो मैं जावा प्रोग्रामर नहीं हूं।

class DaoSingletonFactory
{
    private static Dao dao = null;

    public static Dao getInstance()
    {
        if (DaoSingletonFactory.dao == null) {
            DaoSingletonFactory.dao = new Dao();
        }

        return DaoSingletonFactory.dao;
    }
}

class UsesDao
{
    public void someMethod()
    {
        Dao dao = DaoSingletonFactory.getInstance();
    }
}

यह परीक्षण करने के लिए अविश्वसनीय रूप से कठिन है, क्योंकि आप UsesDaoवर्ग के कोड को बदल दिए बिना कार्यान्वयन को स्वैप नहीं कर सकते । यह कुछ बंदर पैचिंग के माध्यम से किया जा सकता है , लेकिन आमतौर पर एक अच्छा अभ्यास नहीं माना जाता है।

फिर बेहतर तरीका है, कमजोर सिंगलटन पैटर्न, जहां आप एक staticविधि के माध्यम से एक उदाहरण प्राप्त नहीं करते हैं , लेकिन सभी वर्गों को एक निर्माता या एक सेटर के माध्यम से उदाहरण पर निर्भर करते हैं (आपके द्वारा EventSchedulerServiceआप सेटर इंजेक्शन का उपयोग कर रहे हैं)।

एकमात्र समस्या यह है, तो आपको यह सुनिश्चित करने की आवश्यकता है कि सभी वर्ग, जो वर्ग के एक उदाहरण पर निर्भर करते हैं जो केवल आपके आवेदन के जीवन चक्र के बाद ही मौजूद होना चाहिए, अपने पैरामीटर के रूप में एक ही उदाहरण ले रहे हैं, अर्थात। newपूरे आवेदन में डीएओ वस्तु पर केवल एक बार कहा जाता है।

जाहिर है, वस्तु-ग्राफ को ट्रैक करना और निर्माण करना अविश्वसनीय रूप से कठिन है और थकाऊ काम है।

सौभाग्य से, IoC कंटेनर हैं, जो इसे बहुत आसान बनाते हैं। स्प्रिंग के अलावा , Google द्वारा गिटार आईओसी कंटेनर जावा प्रोग्रामर्स के बीच काफी लोकप्रिय है।

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

आप गाइस के साथ एक सिंगलटन उदाहरण के लिए इस लिंक की जांच कर सकते हैं ।


एक आईओसी कंटेनर का उपयोग करने के पेशेवरों और विपक्ष

पेशेवरों

  • सभी फैक्ट्री विधियों को स्वयं न लिखकर बजट की बचत करें
  • (आमतौर पर) बहुत सीधा विन्यास
  • त्वरित विकास

विपक्ष

  • एक जादूगर का जादू, कक्षाएं किसी भी तरह से बनाई जाती हैं और आप वास्तव में नहीं देख सकते कि यह कैसे हुआ
  • क्लास लुकिंग के कारण थोड़ा सा प्रदर्शन ड्रॉप (मैन्युअल रूप से लिखे गए कारखाने थोड़े तेज़ होंगे)

1

सिंगलटन अवधारणा को केवल एक उदाहरण और उदाहरण तक पहुँच प्राप्त करने का तरीका बता रहा है ( इतने प्रसिद्ध स्थैतिक विधि के माध्यम से getInstance () )

लेकिन उस सब के पीछे अभी भी एक उदाहरण है। एक निर्मित वस्तु जिसमें एक प्रकार की प्रतिबंधित पहुंच है।

आपके मामले में, मैं नहीं बल्कि DI दृष्टिकोण (निर्भरता इंजेक्शन) के लिए जाना होगा। कोड के पहले ब्लॉक की तरह आपने उजागर किया है। बस थोड़ा सा बदलाव। कंस्ट्रक्टर के माध्यम से DAO इंजेक्ट करें। सेटर को हटाना या न करना आपके ऊपर है। यदि आप नियंत्रक को रनटाइम में बदलाव से बचाना चाहते हैं तो इसे हटा दें। यदि आप ऐसी संभावना पेश करना चाहते हैं, तो इसे रखें।

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

बस एक संकेत है। स्थैतिक संसाधन (ऑब्जेक्ट, विधियाँ, स्थिरांक या चर) वैश्विक संसाधनों की तरह हैं। अगर ग्लोबल्स बुराई हैं या नहीं तो जरूरत या स्वाद की बात नहीं है। हालांकि उनके लिए निहित कमियां हैं। ये संगति से संबंधित हैं , थ्रेड-सेफ्टी (जावा में, अन्य भाषाओं के बारे में नहीं जानते हैं), क्रमबद्धता ...

इसलिए मैं सावधानी से स्टैटिक्स का उपयोग करने का सुझाव दूंगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.