एक वर्ग के अद्वितीय उदाहरणों को सुनिश्चित करने के तरीके?


14

मैं यह सुनिश्चित करने के लिए विभिन्न तरीकों की तलाश कर रहा हूं कि किसी दिए गए वर्ग का प्रत्येक उदाहरण विशिष्ट पहचान योग्य उदाहरण है।

उदाहरण के लिए, मेरे पास Nameक्षेत्र के साथ एक वर्ग है name। एक बार जब मुझे जॉन स्मिथ के Nameसाथ nameआरंभ करने के लिए एक वस्तु मिलती है, तो मैं जॉन स्मिथ Nameके नाम के साथ एक अलग वस्तु को भी तुरंत प्राप्त करने में सक्षम नहीं होना चाहता हूं , या यदि तात्कालिकता होती है, तो मैं चाहता हूं कि मैं चाहता हूं कि मूल वस्तु का संदर्भ वापस पारित किया जाए। एक नई वस्तु की तुलना में।

मुझे पता है कि ऐसा करने का एक तरीका एक स्थिर कारखाना है जो Mapसभी वर्तमान नाम वस्तुओं को रखता है और कारखाने की जाँच करता है कि जॉन स्मिथ के साथ एक ऑब्जेक्ट जैसा कि नाम एक संदर्भ को वापस भेजने से पहले ही मौजूद नहीं है। Nameवस्तु।

एक और तरीका जिससे मैं सोच सकता था कि मेरे सिर के ऊपर Nameकक्षा में एक स्थैतिक मानचित्र हो रहा है और जब निर्माणकर्ता को एक अपवाद फेंकने को कहा जाता है यदि इसके लिए पारित मूल्य nameपहले से ही किसी अन्य ऑब्जेक्ट में उपयोग में है, लेकिन मुझे पता है कि अपवाद फेंक रहा हूं। एक निर्माता में आमतौर पर एक बुरा विचार है

क्या इसे प्राप्त करने के अन्य तरीके हैं?


1
आप एक गायक

5
आपको पहले एक के साथ बेहतर चलना चाहिए: - स्थैतिक कारखाना
रोहित जैन

16
@MarcB op सिंगलटन नहीं चाहता है। उसके पास एक ही कक्षा के कई उदाहरण हो सकते हैं, लेकिन इन उदाहरणों को पहचानने योग्य होना चाहिए।

1
@MarcB मैं सिंगलटन पैटर्न से वाकिफ हूं लेकिन मैंने सोचा कि यह सुनिश्चित करता है कि कक्षा का केवल एक ही उदाहरण संभव है? मुझे कई उदाहरण, विभिन्न मूल्य चाहिए। क्षमा करें यदि प्रश्न स्पष्ट नहीं हो रहा है। संपादित करें: पोस्ट करने से पहले केवल पहली टिप्पणी देखी।
मूंगफली

2
I'm aware that one way of doing this is to have a static factory that holds a Map...तो आप इसे इस तरह से क्यों नहीं करना चाहते हैं?
FrustratedWithFormsDesigner

जवाबों:


13

वास्तव में आप पहले ही अपने प्रश्न का उत्तर दे चुके हैं। आपका पहला तरीका यहां अधिक प्रभावी होना चाहिए। उपयोग करना static factoryहमेशा बेहतर होता है constructorजहाँ भी आपको लगता है कि आप कर सकते हैं। तो, आप Constructorइस मामले में उपयोग करने से बच सकते हैं , अन्यथा throw some exceptionयदि कोई उदाहरण पहले से ही दिए गए नाम के साथ मौजूद है।

तो, आप एक स्थिर कारखाना विधि बना सकते हैं: - getInstanceWithName(name)जो उस नाम के साथ पहले से ही उपलब्ध इंस्टेंस को प्राप्त कर लेगा, और यदि यह मौजूद नहीं है, तो यह एक नया उदाहरण बना देगा, और आपके constructorनिजी बना देगा , जैसा कि ज्यादातर काम करते समय किया जाना चाहिए। static factories

इसके अलावा, इसके लिए आपको अपनी कक्षा में बनाए गए सभी विशिष्ट उदाहरणों के स्थिर Listया बनाए रखने की आवश्यकता है ।MapFactory

संपादित करें : -

आपको निश्चित रूप से - प्रभावी जावा - आइटम # 1 के माध्यम से जाना चाहिए : कंस्ट्रक्टर्स पर स्थैतिक कारखानों पर विचार करें । आपको उस पुस्तक से बेहतर स्पष्टीकरण नहीं मिल सकता है।


1
ओपी ने पहले से ही ऐसा कुछ सोचा है।
17

लिंक के लिए +1, जो ओपी की कुछ चिंताओं को स्पष्ट रूप से संबोधित करता है।
रॉबर्ट हार्वे

@RobertHarvey। हाँ, यह पुस्तक इन जैसे अधिकांश विषयों के लिए सबसे अच्छा स्रोत है। और यह वास्तव में बहुत पहला आइटम है। :)
रोहित जैन

प्रभावी जावा के लिए +1, मेरे पास पुस्तक है, मेरे बैग में अब वास्तव में बैठी है :) हालांकि मैं स्थिर कारखाने / स्थैतिक विधि और निर्माणकर्ता में अपवाद के अलावा विशिष्टता प्राप्त करने के अन्य तरीकों के लिए उत्सुक था । अगर कोई नहीं है तो मैं इसे स्वीकार करूंगा।
मूंगफली

@Peanut। ज़रूर। अधिक जानकारी प्राप्त करने के लिए खुदाई करने का सबसे अच्छा संसाधन है।
रोहित जैन

5

प्रभावी जावा के Mentions बहुत विश्वसनीयता जोड़ने के लिए लगता है तो यह जवाब आकर्षित करता है:

  • प्रभावी जावा आइटम 8: समतुल्य होने पर सामान्य अनुबंध का पालन करें
  • प्रभावी जावा आइटम 9: जब आप ओवरराइड करते हैं तो हमेशा हैशकोड को ओवरराइड करें
  • प्रभावी जावा आइटम 15: परिवर्तनशीलता को कम करें

मैं एक कदम पीछे ले जाऊंगा और सवाल करूंगा कि आप इस नाम की वस्तु के एक से अधिक उदाहरण क्यों हैं।

मुझे इस तरह के ऑब्जेक्ट पूलिंग करने की शायद ही कभी आवश्यकता होती है। यह मेरा अनुमान है कि ओपी ऐसा कर रहा है ताकि वे बस अपनी Nameवस्तुओं की तुलना कर सकें ==। या कुंजी के रूप में Nameअंदर HashMapया समान वस्तुओं का उपयोग करें ।

यदि ऐसा है तो इसे उचित कार्यान्वयन केequals() माध्यम से हल किया जा सकता है ।

इस तरह:

public final class Name {
  private final String name;

  public Name(String name) {
    if (name == null) {
      name = ""; //or exception if you like
    }
    this.name = name;
  }

  public String getName() {
    return name;
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Name)) {
      return false;
    }
    Name other = (Name) o;
    return other.name.equals(name);
  }

  @Override
  public int hashCode() {
    return name.hashCode();
  }
}

एक बार पूरा करने के बाद यह सही है:

Name a = new Name("weston");
Name b = new Name("weston");
assert(a.equals(b)); //same but:
assert(a!=b); //not the same instance
//test out the Name instances in a hashmap:
HashMap<Name,Object> map = new HashMap<Name,Object>();
Object detailsIn = new Object();
map.put(a,detailsIn);
Object detailsOut = map.get(b);
assert(detailsIn==detailsOut); //the map returned the same details object
//even though we put with `a` and got with `b` thanks to our correct equals implementation

मैं आपके लक्ष्य का अनुमान लगा रहा हूं, लेकिन इस तरह से आप Nameहैश मैप्स आदि में क्लास का उपयोग कर सकते हैं , और उन्हें ठीक उसी तरह का उदाहरण नहीं होना चाहिए।


उदाहरण, कृपया।
रॉबर्ट हार्वे

@RobertHarvey उचित कार्यान्वयन का उदाहरण है?
पश्चिमोत्तर

लगता है कि आपने एक प्रदान किया। लेकिन मैं स्पष्ट नहीं हूं कि यह किसी स्थिर फैक्ट्री पद्धति में समानता के लिए केवल नाम की संपत्ति की जांच से अलग कैसे है।
रॉबर्ट हार्वे

1
@RobertHarvey मैंने अधिक समझाने की कोशिश की है, मैं एक पूर्ण विकल्प प्रदान कर रहा हूं जिसमें स्थिर कारखाने की आवश्यकता नहीं है और मैं ओपी के शुरुआती बिंदु को चुनौती दे रहा हूं कि वे प्रति बार एक से अधिक बार उदाहरण के लिए नहीं चाहते हैं।
पश्चिमोत्तर

यदि आप एक मॉनिटर के रूप में ऑब्जेक्ट का उपयोग करने के लिए सिंक्रनाइज़ ब्लॉक चाहते हैं, तो अद्वितीय ऑब्जेक्ट्स की आवश्यकता के लिए एक वैध कारण है। दो वस्तुएं जो। असमान () एक दूसरे से काम नहीं करेंगी।
Leigh Caldwell

3
  • Nameएक इंटरफ़ेस बनाओ
  • NameFactoryएक विधि के साथ एक इंटरफ़ेस बनाएँName getByName(String)
  • के एक कार्यान्वयन बनाएं NameFactoryएक साथ Map<String,WeakReference<Name>>इसके अंदर
  • synchronizeके getByNameनए उदाहरण बनाने से पहले विधि के अंदर नाम से मानचित्र परName
  • वैकल्पिक रूप से, Nameअपने कार्यान्वयन के अंदर इंटरफ़ेस के एक स्थिर निजी कार्यान्वयन का उपयोग करेंNameFactory

यह दृष्टिकोण आपको यह सुनिश्चित करने देगा कि:

  • Nameकिसी भी समय केवल एक ही उदाहरण मौजूद है,
  • आपकी कक्षा में कोई "Lingerer" मेमोरी लीक नहीं है, जब Nameवे जरूरत से ज्यादा देर तक चिपके रहते हैं,
  • डिजाइन नकली वस्तुओं के साथ परीक्षण योग्य रहता है, क्योंकि आप इंटरफेस का उपयोग करते हैं।

यदि आपके पास throwकिसी ऑब्जेक्ट को वापस करने के बजाय समान नाम मौजूद है, या यदि आप किसी nullऑब्जेक्ट को वापस करते हैं , तो आपके पास फ़ैक्टरी विधि के साथ मेमोरी लीक नहीं है ।
रॉबर्ट हार्वे

@ रोबर्टह्वे का मतलब है कि लीक जो वास्तव में लीक नहीं हैं, लेकिन वैध वस्तुएं (तथाकथित "लिंजर्स")। एक साधारण स्थैतिक मानचित्र इसके मूल्य वस्तुओं को रिलीज़ होने से रोकता है, जबकि कमजोर संदर्भों का एक मानचित्र उन्हें केवल स्मृति में तब तक धारण करेगा जब तक कि अन्य सजीव संदर्भ अस्तित्व में हैं।
dasblinkenlight

ओह, अब समझा तुम्हारा क्या मतलब है। यह उन दुर्लभ उदाहरणों में से एक destructorहो सकता है जहां यह आसान होगा।
रॉबर्ट हार्वे

1
बहुत जटिल। यह @ वेस्टन उत्तर की तरह किया जा सकता है, बराबरी से अधिक हो सकता है और कारखाने में नामों का संग्रह रख सकता है।
ट्यूलेंस कोरडोवा

@ user1598390 किसी व्यक्ति को जितना संभव हो उतना सरल बनाना चाहिए, लेकिन कोई सरल नहीं है। वेस्टन का "समाधान" ओपी की समस्या को हल नहीं करता है (कोई नक्शा नहीं है), और नामों का एक संग्रह लिंजर मेमोरी लीक बनाता है (हां, जावा में मेमोरी लीक हैं)।
dasblinkenlight

1

आपको कंस्ट्रक्टरों को निजी बनाना चाहिए और ऐसे तरीके बनाने चाहिए getNameInstance(String), यदि एक ही नाम वाली कोई वस्तु पहले से मौजूद हो (उदाहरण के लिए एक स्थिर वर्ग के आधार पर), तो आप उस संदर्भ को वापस कर देते हैं, अन्यथा आप अपने निजी कंस्ट्रक्टर का उपयोग करके एक नया ऑब्जेक्ट बनाते हैं और इसे जोड़ते हैं हैशटेबल के लिए


आपने प्रश्न के तीसरे पैराग्राफ में जो कहा है उसे आपने दोहराया है। मैं वैकल्पिक तरीकों के बाद था।
मूंगफली

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

1

निम्नलिखित का प्रयास करें। आपको अपने द्वारा बनाए गए प्रत्येक ऑब्जेक्ट का ट्रैक रखना होगा। इस उद्देश्य के लिए मैं सूची का उपयोग कर रहा हूं। और क्लास कंस्ट्रक्टर को निजी बना दिया, ताकि एक उदाहरण बनाने से पहले प्री-चेक लागू किया जा सके

class UniqueName
    {
        private string Name;
        public int ID;
        private static int Count=0;
        static List<UniqueName> lt=new List<UniqueName>();

        private UniqueName(string Name)
        {
            this.Name = Name;
            ID = ++Count;
        }

        public static UniqueName GetUniqueueInstance(string Name)
        {
            foreach (UniqueName un in lt)
            {
                if ( string.Compare( un.Name,Name,StringComparison.InvariantCultureIgnoreCase)==0)
                    return un;
            }

            UniqueName temp=new UniqueName(Name);
            lt.Add(temp);
            return temp;
        }
    }

यह जावा नहीं है? क्या आपने एक छद्म कोड लिखा है? या, किसी अन्य भाषा में? कृपया स्पष्ट रूप से निर्दिष्ट करें।
रोहित जैन

सी # लगती है। अक्षय, आपको इसके अलावा अन्य संग्रह सीखना चाहिए List। यह एक अच्छा फिट होगा Dictionary<string,UniqueName>
वेस्टन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.