2011-07-05 12 views
6

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

class XMLModel 
    class V1 
    # V1 specific implementation 
    end 

    class V2; 
    # V2 specific implementation 
    end 

    def initialize 
    # create a new V? and set up delegation to that specific version of the object 
    end 

    def from_xml(xml_string) 
    # use the XML string to determine correct version and return a 
    # specific version of the object 
    end 
end 

उपरोक्त विधि के बारे में अच्छी बात यह है प्रत्येक संस्करण के कोड के भीतर अलग है, और मुझे जोड़ने की अनुमति है कि है/ड्रॉप छोटे पीछे संगतता परीक्षण के साथ संस्करण। बुरी बात यह है कि मैं संभवतः बहुत सारे कोड डुप्लिकेशंस के साथ समाप्त हो जाऊंगा। इसके अलावा, इस मामले में, XMLModel.new एक नया XMLModel देता है, जबकि XMLModel.from_xml फैक्टरी विधि एक नया XMLModel::V1 देता है।

विचार?

उत्तर

2

XMLModel से प्राप्त होने वाले उप-वर्ग का निर्माण क्यों न करें, फिर कक्षाओं के बीच निर्णय कोड में केवल एक बिंदु पर है।

class XMLModel_V1 < XMLModel 
    def from_xml(xml_string) 
     # do V1 specific things 
    end 
end 

class XMLModel_V2 < XMLModel 
    def from_xml(xml_string) 
     # do V2 specific things 
    end 
end 


# Sample code wich shows the usage of the classes 
if(V1Needed) 
    m = XMLModel_V1 
else 
    m = XMLModel_V2 
end 
+0

आप छिपा सकते हैं कि XMLModel प्रारंभ (अर्थात 'new') में' if' बयान ... मैं एक अलग कारखाने intialization है, यानी 'XMLModel.create' का उपयोग किए बिना नहीं कर पा रहे। मैं लोगों को संस्करण के बारे में नहीं जानना चाहता हूं और सामान्य रूबी ऑब्जेक्ट के रूप में ऑब्जेक्ट का उपयोग करने में सक्षम हूं और 'XMLModel.new' पर कॉल कर रहा हूं, इस प्रकार मॉडल के पीछे सभी कार्यान्वयन को छुपा रहा हूं। –

+0

आप ':: new' को ओवरराइड कर सकते हैं। डिफ़ॉल्ट नई विधि (मुझे लगता है) कुछ ऐसा है: 'def new (* args); obj = आवंटित करें; obj.initialize (* args); obj retrun; अंत 'एक लाइनर के लिए खेद है, टिप्पणियां और कोड अच्छी तरह से मिश्रण नहीं करते हैं। – Ian

+0

ने फिर से परिभाषित करने के अधिक विस्तार के साथ एक उत्तर जोड़ा :: नया – Ian

3

मुझे आपके लिए कुछ विकल्प दिखाई देते हैं।

आप XMLModel पर method_missing पर विधि कॉल प्रॉक्सी कर सकते हैं।

class XMLModel 

    def load_xml(xml) 
    version = determine_version(xml) 
    case version 
    when :v1 
     @model = XMLModelV1.new 
    when :v2 
     @model = XMLModelV2.new 
    end 
    end 

    def method_missing(sym, *args, &block) 
    @model.send(sym, *args, &block) 
    end 

end 

एक अन्य विकल्प गतिशील XMLModel के कहने के लिए एक विशिष्ट संस्करण से तरीकों कॉपी करने के लिए किया जाएगा। हालांकि, जब तक पूरी तरह से जरूरी नहीं है, मैं इसे करने से हतोत्साहित करता हूं।

तीसरा विकल्प प्रत्येक संस्करण के लिए एक मॉड्यूल बनाना है जिसमें उस संस्करण के लिए विशिष्ट विधियां हैं। फिर, प्रॉक्सी ऑब्जेक्ट रखने के बजाय आप केवल विशेष संस्करण के लिए मॉड्यूल शामिल करेंगे।

module XMLModelV1 
    #methods specific to v1 
end 

module XMLModelV2 
    #methods specific to v2 
end 

class XMLModel 
    #methods common to both versions 

    def initialize(version) 
    load_module(version) 
    end 

    def load_xml(xml) 
    load_module(determine_version(xml)) 
    end 

private 

    def load_module(version) 
    case version 
    when :v1 
     include XMLMOdelV1 
    when :v2 
     include XMLModelV2 
    end 
    end 
end 
+0

यह एक्सएमएल लोड करते समय काम करेगा, लेकिन एक्सएमएल बनाने का प्रयास करते समय काम नहीं करेगा। क्या आप सोच रहे हैं कि मुझे इसके लिए एक गैर-'नई' फैक्ट्री विधि का भी उपयोग करना चाहिए (यानी 'बनाओ')? –

+0

'to_xml' विधि विशिष्ट संस्करण वर्गों में से किसी एक का हिस्सा नहीं होगा? – Jeremy

+0

हां, to_xml प्रत्येक वर्जन वर्ग का हिस्सा होगा, लेकिन यदि उपयोगकर्ता स्क्रैच से एक्सएमएल दस्तावेज़ बनाना चाहता है, तो उसे एक नया (खाली) ऑब्जेक्ट प्राप्त करने की आवश्यकता है जिसे वे सेटर विधियों को कॉल करके 'भरें' कर सकते हैं, sorta- रेल सक्रिय ActiveRecord की तरह। –

2

यह एक पूर्ण उत्तर नहीं है, लेकिन मेरी टिप्पणी का एक बेहतर प्रारूपित संस्करण वर्णन करता है कि आप कैसे :: ओवरराइड कर सकते हैं।

class XMLModel 
    def new *args 
    if self == XMLModel 
     klass = use_v1? ? XMLModelV1 : XMLModelV2 
     instance = klass.allocate 
     instance.initialize *args 
     instance   
    else 
     super *args 
    end 
    end 
end 
# and of course: 
class XMLModelV1 < XMLModel; end 
class XMLModelV2 < XMLModel; end 
संबंधित मुद्दे