2009-04-15 7 views

उत्तर

18

यह एक प्रयोग करने योग्य पर्याप्त पैटर्न अगर वहाँ बातें एक वस्तु पर तय करने की आवश्यकता है कि का एक बहुत है।

class Foo 
{ 
     int x, y, z; 
public: 
     Foo &SetX(int x_) { x = x_; return *this; } 
     Foo &SetY(int y_) { y = y_; return *this; } 
     Foo &SetZ(int z_) { z = z_; return *this; } 
}; 

int main() 
{ 
     Foo foo; 
     foo.SetX(1).SetY(2).SetZ(3); 
} 

यह पैटर्न एक निर्माता है कि तीन ints लेता बदल देता है:

int main() 
{ 
     Foo foo(1, 2, 3); // Less self-explanatory than the above version. 
} 

अगर आप मान हमेशा तय करने की आवश्यकता नहीं है कि की एक संख्या है यह उपयोगी है।

संदर्भ के लिए, इस प्रकार की तकनीक का एक और पूर्ण उदाहरण सी ++ एफएक्यू लाइट में "Named Parameter Idiom" के रूप में प्रस्तुत किया जाता है।

बेशक

, यदि आप नाम वाले पैरामीटर के लिए यह प्रयोग कर रहे हैं, तो आप boost::parameter पर एक नज़र डालें कर सकते हैं। या आप नहीं हो सकता है ...

+0

मैं हाल ही में इस तकनीक से चिंतित हूं। यह देखना दिलचस्प होगा कि कोई भी किसी भी कमी के साथ आता है या नहीं। –

+0

दिलचस्प। मैंने इसे जटिल रचनाकारों के विकल्प के रूप में नहीं माना था। यह तकनीक कन्स्ट्रक्टर ओवरलोड की एक बड़ी संख्या में कटौती कर सकती है। –

+1

ऐसी कुछ चीजें हैं जिनके साथ आप ऐसा नहीं कर सकते हैं कि आप रचनाकारों (जैसे कि कॉन्स्ट और संदर्भों को प्रारंभ करना) – Eclipse

0

मुझे ऐसा लगता है नहीं होगा। आम तौर पर, आप 'सेटटर' ऑब्जेक्ट के बारे में सोचते हैं।

इसके अलावा, अगर आप सिर्फ वस्तु निर्धारित करते हैं, आप इसे करने के लिए एक सूचक वैसे भी है न?

2

नहीं सभी setters, लेकिन उनमें से कुछ लौट सकते हैं संदर्भ उपयोगी हो पर आपत्ति उठाने का।

तरह का

a.SetValues(object)(2)(3)(5)("Hello")(1.4); 

मैं इस एक बार बहुत समय पहले इस्तेमाल किया एसक्यूएल अभिव्यक्ति बिल्डर जो सभी पलायन समस्याओं और अन्य चीजें संभालती बनाने के लिए।

SqlBuilder builder; 

builder.select(column1)(column2)(column3). 
    where("=")(column1, value1) 
       (column2, value2). 
    where(">")(column3, 100). 
    from(table1)("table2")("table3"); 

मैं 10 मिनट में स्रोतों को पुन: उत्पन्न करने में सक्षम नहीं था। तो पर्दे के पीछे कार्यान्वयन है।

+0

मैंने सी ++ में एक्सएमएल दस्तावेजों के निर्माण के लिए समान सामान किया है। हालांकि यहां सवाल सामान्य संपत्ति सेटर्स के बारे में प्रतीत होता है। –

10

यदि आप श्रृंखला सेटर समारोह करना चाहते this के लिए एक संदर्भ लौट सकते हैं इस तरह एक साथ कॉल:

obj.SetCount(10).SetName("Bob").SetColor(0x223344).SetWidth(35); 

निजी तौर पर मुझे लगता है कि कोड कठिन है विकल्प की तुलना में पढ़ने के लिए:

obj.SetCount(10); 
obj.SetName("Bob"); 
obj.SetColor(0x223344); 
obj.SetWidth(35); 
+0

यह लेआउट का सवाल है। आप केवल दूसरे भाग को लिख सकते हैं, बस ओबीजे को छोड़कर। सब कुछ पर लेकिन पहले और; आखिरी लेकिन सब कुछ पर। आईएमएचओ, यह तब पठनीय है। संकलन-समय सुरक्षा के लिए –

2

यदि आपकी प्रेरणा चेनिंग से संबंधित है (उदाहरण के लिए ब्रायन एनसिंक के सुझाव), तो मैं दो टिप्पणियों की पेशकश करूंगा:

1. यदि यो आप स्वयं को अक्सर कई चीजों को एक साथ देखते हैं, इसका मतलब यह हो सकता है कि आपको struct या class का उत्पादन करना चाहिए जिसमें इन सभी सेटिंग्स को रखा गया है ताकि वे सभी एक बार में पारित हो सकें। अगला चरण ऑब्जेक्ट में इस struct या class का उपयोग करना हो सकता है ... लेकिन चूंकि आप गेटर्स और सेटर्स का उपयोग कर रहे हैं, इसका आंतरिक रूप से प्रतिनिधित्व करने का निर्णय कक्षा के उपयोगकर्ताओं के लिए पारदर्शी होगा, इसलिए यह निर्णय होगा इस बात से अधिक संबंधित है कि कक्षा किसी भी चीज़ से कितनी जटिल है।

2. एक सेटर का एक विकल्प एक नई वस्तु बना रहा है, इसे बदल रहा है, और इसे वापस कर रहा है। यह ज्यादातर प्रकार, विशेष रूप से परिवर्तनीय प्रकारों में अक्षम और अनुचित दोनों है। हालांकि, यह एक विकल्प है कि कई भाषाओं की स्ट्रिंग क्लास में इसका उपयोग करने के बावजूद लोग कभी-कभी भूल जाते हैं।

2

इस शैली के लिए सामान्य उद्देश्य ऑब्जेक्ट निर्माण के लिए उपयोग में है।

Person* pPerson = &(new Person())->setAge(34).setId(55).setName("Jack"); 

Person* pPerson = new Person(34, 55, "Jack"); 

दूसरा अधिक परंपरागत शैली अगर पहला मान निर्माता के लिए पारित उम्र या आईडी था एक भूल भी सकते हैं का उपयोग करने के बजाय

? इससे कुछ गुणों की वैधता के आधार पर कई रचनाकार भी हो सकते हैं।

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

कोड विकसित होने के बाद मुझे वास्तव में यह तथ्य पसंद है कि मैं सभी स्थानों को ढूंढने में मदद करने के लिए कंपाइलर का उपयोग कर सकता हूं जहां एक कन्स्ट्रक्टर के हस्ताक्षर को बदलते समय ऑब्जेक्ट बनाया जाता है। इसलिए इसी कारण से मैं इस शैली पर नियमित सी ++ रचनाकारों का उपयोग करना पसंद करता हूं।

  • आप एक तालिका में एक क्षेत्र/विशेषता जोड़ सकते हैं/वर्ग कि शून्य है:

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

  • कोड जो परिवर्तन नहीं है, अभी भी इस न्यूल फ़ील्ड के साथ समान कार्य करना चाहिए।
+0

+1। – Eclipse

+0

वाह। यह नामित पैरामीटर की सी ++ की कमी के लिए एक अद्भुत अनुकूलन है (जैसे अडा के पास 20 साल हैं)। –

+0

-> नहीं। पॉइंटर्स के लिए हालांकि :) –

3

IMO setters एक कोड गंध कि आम तौर पर संकेत मिलता है दो चीजों में से एक:

class Gizmo 
{ 
public: 
    void setA(int a) { a_ = a; } 
    int getA() const { return a_; } 

    void setB(const std::string & b) { v_ = b; } 
    std::string getB() const { return b_; } 
private: 
    std::string b_; 
    int a_; 
}; 
:

राई

का एक Mountian आउट बनाना आप इस तरह एक वर्ग है, तो

... और मूल्य वास्तव में इतना आसान हैं, तो क्यों न केवल डेटा सदस्यों को सार्वजनिक करें ?:

class Gizmo 
{ 
public: 
    std::string b_; 
    int a_; 
}; 

... बहुत सरल और, अगर डेटा कि सरल आप कुछ भी नहीं खोना है। , हो सकता है आप एक से अधिक मान बदलने के लिए, कुछ गणना करते हैं:

एक और संभावना है कि आप

हो सकता है कई बार Mountian

बहुत सारे डेटा इतना आसान नहीं है का एक राई आउट बनाना है कुछ अन्य वस्तु को सूचित करें; कौन जानता है लेकिन यदि डेटा इतना छोटा नहीं है कि आपको वास्तव में & गेटर्स सेटर्स की आवश्यकता है, तो यह त्रुटि प्रबंधन की आवश्यकता के लिए पर्याप्त गैर-तुच्छ है। तो उन मामलों में आपके गेटर्स & सेटर्स को किसी प्रकार का त्रुटि कोड वापस करना चाहिए या कुछ बुरा करने के संकेत देने के लिए कुछ और करना चाहिए।

आप इस तरह एक साथ कॉल चेनिंग रहे हैं:

A.doA().doB().doC(); 

... और DOA() विफल रहता है, तुम सच में चाहते हैं जन्म तिथि() और डॉक्टर() वैसे भी कॉल कर रहे हैं? मुझे शक है।

+6

आरई: "एडोए()। डीओबी()। डीओसी();" अगर डू विफल रहता है, तो यही अपवाद है। – Eclipse

+0

+1, अच्छा बिंदु जॉन। जोश भी अच्छा मुद्दा है। –

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