2008-11-20 16 views
5

मैं जावा बीन्स के लिए अपरिवर्तनीयता प्रदान करने की संभावना के बारे में बहुत उत्सुक हूं (यहां बीन्स द्वारा मेरा मतलब है कि एक खाली कन्स्ट्रक्टर के साथ कक्षाएं जो सदस्यों के लिए गेटर्स और सेटर्स प्रदान करती हैं)। स्पष्ट रूप से ये कक्षाएं अपरिवर्तनीय नहीं हैं और जहां उनका उपयोग डेटा परत से मूल्यों को परिवहन करने के लिए किया जाता है, यह वास्तविक समस्या की तरह लगता है।जावा में अपरिवर्तनीय सेम

स्टैक ओवरव्लो में इस समस्या का एक दृष्टिकोण यहां उल्लेख किया गया है जिसे "सी # में अपरिवर्तनीय ऑब्जेक्ट पैटर्न" कहा जाता है जहां ऑब्जेक्ट पूरी तरह से बनाया गया है। मेरे पास एक वैकल्पिक दृष्टिकोण है और वास्तव में लोगों की राय सुनना अच्छा लगेगा।

पैटर्न में दो वर्ग अपरिवर्तनीय और उत्परिवर्तनीय होते हैं जहां उत्परिवर्तनीय और अपरिवर्तनीय दोनों एक इंटरफेस को लागू करते हैं जो गैर-उत्परिवर्तनीय बीन विधियों को प्रदान करता है।

उदाहरण

public interface DateBean { 
    public Date getDate(); 
    public DateBean getImmutableInstance(); 
    public DateBean getMutableInstance(); 
} 

public class ImmutableDate implements DateBean { 
    private Date date; 

ImmutableDate(Date date) { 
    this.date = new Date(date.getTime()); 
} 

public Date getDate() { 
    return new Date(date.getTime()); 
} 

    public DateBean getImmutableInstance() { 
     return this; 
    } 

    public DateBean getMutableInstance() { 
     MutableDate dateBean = new MutableDate(); 
     dateBean.setDate(getDate()); 
     return dateBean; 
    } 
} 

public class MutableDate implements DateBean { 
    private Date date; 

public Date getDate() { 
    return date; 
} 

public void setDate(Date date) { 
    this.date = date; 
} 

public DateBean getImmutableInstance() { 
    return new ImmutableDate(this.date); 
} 

    public DateBean getMutableInstance() { 
     MutableDate dateBean = new MutableDate(); 
     dateBean.setDate(getDate()); 
     return dateBean; 
    } 
} 

यह दृष्टिकोण के लिए अनुमति देता है सेम (सामान्य सम्मेलनों द्वारा) प्रतिबिंब का उपयोग कर निर्माण किया जा करने के लिए और भी हमारे पास अवसर पर अपरिवर्तनीय संस्करण में बदलने के लिए अनुमति देता है। दुर्भाग्य से प्रति बीन बॉयलरप्लेट की बड़ी मात्रा स्पष्ट रूप से है।

मुझे इस मुद्दे पर अन्य लोगों के दृष्टिकोण को सुनने में बहुत दिलचस्पी है। (एक अच्छा सवाल है, जो बजाय जवाब दिया जा सकता चर्चा की :)

उत्तर

2

मुझे लगता है कि मैं प्रतिनिधिमंडल पैटर्न का उपयोग करें - एक ही DateBean सदस्य है कि निर्माता में निर्दिष्ट किया जाना चाहिए के साथ एक ImmutableDate वर्ग बनाने: मैं अचल स्थिति के लिए मजबूर करने की जरूरत है कभी

public class ImmutableDate implements DateBean 
{ 
    private DateBean delegate; 

    public ImmutableDate(DateBean d) 
    { 
     this.delegate = d; 
    } 

    public Date getDate() 
    { 
     return delegate.getDate(); 
    } 
} 

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

फिर भी यह कठिन बॉयलरप्लेट कोड है लेकिन यह ऐसी चीज है कि ग्रहण की तरह एक अच्छा आईडीई केवल कुछ माउस क्लिक के साथ आपके लिए स्वत: उत्पन्न कर सकता है।

यदि यह ऐसी चीज है जो आप कई डोमेन ऑब्जेक्ट्स पर कर रहे हैं, तो आप गतिशील प्रॉक्सी या शायद एओपी का उपयोग करने पर विचार करना चाहेंगे। किसी भी ऑब्जेक्ट के लिए प्रॉक्सी बनाने, सभी प्राप्त विधियों को प्रस्तुत करने और उचित तरीके से सेट विधियों को फँसाने या अनदेखा करना अपेक्षाकृत आसान होगा।

+0

यह एक बहुत अच्छा विचार है। यह समस्या बहुत सुंदर ढंग से फिट बैठता है। चीयर्स क्रिस –

+0

यदि यह डेटबीन में आयोजित दिनांक वस्तु है, तो आपको प्राप्त करने के लिए एक नई तिथि बनाना होगा। अन्यथा आप ImmutableDate.getDate() सेट के माध्यम से दिनांक को संशोधित कर सकते हैं .... सेट करें .... – monksy

3

कुछ टिप्पणियां (जरूरी नहीं समस्याओं) प्रदान नहीं करने के लिए मेरे क्षमायाचना:

  1. दिनांक वर्ग ताकि आप सही ढंग से करने के लिए इसे कॉपी कर रहे हैं अपने आप में परिवर्तनशील है अपरिवर्तनीयता की रक्षा करें, लेकिन व्यक्तिगत रूप से मैं कन्स्ट्रक्टर में लंबे समय तक परिवर्तित करना पसंद करता हूं और गेटटर में एक नई तिथि (लांगवैल्यू) लौटाता हूं।
  2. आपके दोनों को प्राप्त करें जो कुछ भी शामिल है() विधियां डेटबीन लौटाती हैं जिन्हें कास्टिंग की आवश्यकता होगी, इसके बजाय इंटरफ़ेस को विशिष्ट प्रकार को वापस करने के लिए बदलने का विचार हो सकता है।
  3. यह कहकर कि मैं केवल दो वर्गों को एक उत्परिवर्तनीय और एक अपरिवर्तनीय रखने के इच्छुक हूं, यदि उचित हो तो एक आम (यानी केवल प्राप्त करें) इंटरफ़ेस साझा करना। यदि आपको लगता है कि बहुत सारे रूपांतरण आगे और आगे होंगे तो दोनों कक्षाओं में एक प्रतिलिपि बनाएँ।
  4. मैं संकलक को अपरिवर्तनीयता लागू करने के लिए अंतिम के रूप में फ़ील्ड घोषित करने के लिए अपरिवर्तनीय कक्षाएं पसंद करता हूं।

उदा।

public interface DateBean { 
    public Date getDate(); 
} 

public class ImmutableDate implements DateBean { 
    private final long date; 

    ImmutableDate(long date) { 
     this.date = date; 
    } 

    ImmutableDate(Date date) { 
     this(date.getTime()); 
    } 

    ImmutableDate(DateBean bean) { 
     this(bean.getDate()); 
    } 

    public Date getDate() { 
     return new Date(date); 
    } 
} 


public class MutableDate implements DateBean { 
    private long date; 

    MutableDate() {} 

    MutableDate(long date) { 
     this.date = date; 
    } 

    MutableDate(Date date) { 
     this(date.getTime()); 
    } 

    MutableDate(DateBean bean) { 
     this(bean.getDate()); 
    } 

    public Date getDate() { 
     return new Date(date); 
    } 

    public void setDate(Date date) { 
     this.date = date.getTime(); 
    } 

} 
+0

आपकी टिप्पणियों के लिए धन्यवाद। मैं मानता हूं कि कॉपी कन्स्ट्रक्टर इंटरफ़ेस फैक्ट्री विधियों पर एक महत्वपूर्ण सुधार है। अंतिम सदस्यों पर नोट अच्छी तरह से लिया जाता है। चीयर्स। –

1

मैं बीन्स की उत्परिवर्तन को नियंत्रित करने के लिए इंटरफेस और कास्टिंग का उपयोग करता हूं। मुझे getImmutableInstance() और getMutableInstance() जैसी विधियों के साथ मेरी डोमेन ऑब्जेक्ट्स को जटिल करने का एक अच्छा कारण नहीं दिख रहा है।

क्यों न केवल विरासत और अमूर्तता का उपयोग करें? जैसे

public void validateUser(User user){ 
    if(user.getName() == null) ... 
} 

public void updateUserAge(MutableUser user, int age){ 
    user.setAge(age); 
} 

यह आपके प्रश्न का उत्तर:

public interface User{ 

    long getId(); 

    String getName(); 

    int getAge(); 

} 

public interface MutableUser extends User{ 

    void setName(String name); 

    void setAge(int age); 

} 

यहाँ कोड की ग्राहक क्या कर रही होगी है?

वाईसी

+0

मुझे लगता है कि आप यूजर इंटरफेस को बढ़ाने के लिए MutableUser इंटरफेस के लिए मतलब है? कहने की जरूरत नहीं है कि अभी भी एक ठोस वर्ग की आवश्यकता है। नीचे की तरफ यह है कि यह आपको "अपरिवर्तनीय" को एक साधारण कलाकार द्वारा परिवर्तनीय रूप से परिवर्तित करने के लिए खुलता है, जो संभवतः आप जो चाहते हैं वह संभव नहीं है। –

+0

हालांकि यह सच है कि उपयोगकर्ता इंटरफ़ेस उस उपयोगकर्ता ऑब्जेक्ट को म्यूट करने के तरीकों को प्रदान नहीं करता है जो इसके चेहरे पर नहीं है क्योंकि अपरिवर्तनीयता की गारंटी मजबूत है क्योंकि मैं इस पैटर्न से पूछूंगा। –

+0

हालांकि मुझे लगता है कि आपका दृष्टिकोण एक अच्छा कामकाजी समाधान प्रदान करता है जहां प्रकार (उपयोगकर्ता) निहित रूप से सुझाव देता है कि उपयोगकर्ता को उत्परिवर्तित नहीं किया जाना चाहिए। कई संदर्भों में यह शायद पर्याप्त है। धन्यवाद। –

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