2011-11-16 6 views
7

क्या इसके लिए कोई नाम है:क्या यह एक डिज़ाइन पैटर्न है - इसे सेटर्स से वापस कर रहा है?

class A 
{ 
    A* setA() 
    { 
     //set a 
     return this; 
    } 
    A* setB() 
    { 
     //set b 
     return this; 
    } 
}; 

ताकि आप ऐसा कुछ कर सकें:

A* a = new A; 
a->setA()->setB(); 

क्या इसका उपयोग करने में कोई कमी है? फायदे?

+7

मुख्य दोष यह है कि आप लौट जा सकता है 'है * एक' एक और ', और जैसा कि this'' लेखन ए * एक = नया एक। ए-> setA()। setB() 'या (अधिक महत्वपूर्ण) 'ए बी; । B.setA() setb(); '। 'b.setA() -> setB(); 'थोड़ा कचरा है ;-) –

उत्तर

9

यह विधि चेनिंग (FAQ link) के रूप में जाना जाता है, और अधिक सामान्यतः संदर्भ, नहीं संकेत के साथ किया जाता है।

विधि श्रृंखलन दृढ़ता से नाम पैरामीटर मुहावरा (FAQ link) से संबद्ध है, के रूप में मैं अब, इस उत्तर के एक प्रारंभिक संस्करण पोस्टिंग के बाद, कि Steve Jessop discusses in his answer देखते हैं। एनपीआई मुहावरे कन्स्ट्रक्टर कॉल में जटिलता को मजबूर किए बिना बड़ी संख्या में डिफॉल्ट तर्क प्रदान करने का एक आसान तरीका है। उदाहरण के लिए, यह जीयूआई प्रोग्रामिंग के लिए प्रासंगिक है।

विधि श्रृंखला तकनीक के साथ एक संभावित समस्या तब होती है जब आप विरासत पदानुक्रम में कक्षाओं के लिए एनपीआई मुहावरे को लागू करना चाहते हैं। फिर आप पाते हैं कि C++ कॉन्वर्सेट विधियों का समर्थन नहीं करता है। यह क्या है: जब आप कक्षाओं की विरासत की एक श्रृंखला में कक्षाओं को ऊपर या नीचे घूमते हैं, तो एक कॉन्वेंट विधि वह होती है जिसकी परिभाषा में कुछ प्रकार शामिल होता है जो आपकी घूमने वाली आंखों के लिए विशिष्टता में भिन्न होता है जैसे कि ’ एस

clone विधि को परिभाषित करने के समान ही समस्या है, जिसमें सभी वर्गों में समान पाठ्य परिभाषा है, लेकिन सही प्रकार प्राप्त करने के लिए प्रत्येक कक्षा में श्रमिक रूप से दोहराया जाना चाहिए।

उस समस्या को हल करना भाषा समर्थन के बिना कठिन है; यह एक अंतर्निहित जटिल समस्या प्रतीत होता है, सी ++ प्रकार प्रणाली के साथ एक तरह का संघर्ष। मेरे “How to do typed optional arguments in C++98” blog post कॉन्वेंट परिभाषाओं की पीढ़ी को स्वचालित करने के लिए प्रासंगिक स्रोत कोड से लिंक, और डॉ। डॉब्स जर्नल में इसके बारे में मैंने जो लेख लिखा था, उसके लिए लिंक। हो सकता है कि मैं सी ++ 11, या कभी-कभी, क्योंकि जटिलता और संभावित ब्रितलाइटी ’ के लायक और नरक की तुलना में बड़ी लागत के रूप में दिखाई देगी;

चीयर्स & hth,

+0

ट्रैक से बहुत दूर हो जाता है यहां दिए गए अक्सर पूछे जाने वाले प्रश्न आईएसओ सीपीपी को अपडेट किए जाने चाहिए। मैंने गलत तरीके से किसी के संपादन को अस्वीकार कर दिया। (Http://meta.stackexchange.com/questions/249938/i-incorrectly-rejected-some-edits-what-to-do) –

4

मैंने सुना है कि इसे पहले "method chaining" कहा जाता है, लेकिन मैं इसे एक डिज़ाइन पैटर्न नहीं कहूंगा। (कुछ लोगों को भी एक "fluent interface" को लागू करने के लिए इस का उपयोग कर के बारे में बात - मैं इसे कहा जाता है कि इससे पहले कि हालांकि, लेकिन Martin Fowler एक समय पहले इसके बारे में लिखा है लगता है कभी नहीं देखा था)

आप ऐसा करने से ज्यादा नहीं खोना - यदि आप इसका उपयोग नहीं करना चाहते हैं तो आप हमेशा रिटर्न परिणाम को आसानी से अनदेखा कर सकते हैं।

यह करने के लायक है कि मुझे कम यकीन है। यह कुछ परिस्थितियों में काफी गूढ़ हो सकता है। हालांकि मूल रूप से को की आवश्यकता होती है, जैसे operator<< स्ट्रीम आधारित आईओ के लिए। मैं कहूंगा कि यह एक कोड है कि यह शेष कोड के साथ कैसे फिट बैठता है - क्या यह लोगों को पढ़ने के लिए उम्मीद/स्पष्ट है?

0

यह आमतौर पर में उदाहरण बूस्ट के लिए प्रयोग किया जाता है (जैसा कि स्टीव जेसप ने बताया इस लगभग हमेशा संदर्भ हालांकि, संकेत नहीं के साथ किया जाता है), लेकिन समय के सबसे अधिक कार्यों के बजाय संदर्भ देता है:

A &setX() 
{ 
    // ... 
    return *this; 
} 

class Foo : public A 
{ 
public: 
    Foo *setC() 
    { 
    // set C 
    return this; 
    } 
}; 

तो आपको setters फोन महत्वपूर्ण है:

2

एक नकारात्मक पक्ष यह है कि यदि आप एक से एक वर्ग निकाले जाते हैं, इस तरह कहना है। आप पहली बार फू पर सभी setters कॉल करने के लिए की आवश्यकता होगी: उदाहरण के लिए, इस काम करेंगे नहीं:

Foo f=new Foo(); 
f->setA()->setC(); 

इस वसीयत जबकि:

Foo f=new Foo(); 
f->setC()->setA(); 
+0

अच्छा बिंदु - यही कारण है कि कुछ लिखना संभव नहीं है' (std :: ostringstream() <<" hi "<< 0) .str() 'अगर यह काम करता है तो यह एक बहुत ही आसान मुहावरे होगा। – Flexo

+0

@awoodland: क्या आप 'टेम्पलेट std :: ostringstream और ऑपरेटर << (std :: ostringstream & o, const t & t) {static_cast (o) << t; वापसी ओ; } ', या वह टेम्पलेट' ओस्ट्रीम 'के साथ मौजूदा फ़ंक्शन की तुलना में कम अच्छा मिलान है? –

+0

@SteveJessop - एक व्युत्पन्न प्रकार बेस प्रकार की तुलना में बेहतर मिलान होगा, लेकिन जब मैंने अभी कोशिश की तो यह काम नहीं कर रहा है। मैं कोशिश करूँगा और क्यों पता लगाऊंगा। – Flexo

3

एक अन्य आम-ish उपयोग "पैरामीटर वस्तुओं के साथ है "। विधि श्रृंखला के बिना, वे स्थापित करने के लिए काफी असुविधाजनक हैं, लेकिन इसके साथ वे अस्थायी हो सकते हैं।

बजाय:

complicated_function(P1 param1 = default1, P2 param2 = default2, P3 param3 = default3); 

लिखें:

struct ComplicatedParams { 
    P1 mparam1; 
    P2 mparam2; 
    P3 mparam3; 
    ComplicatedParams() : mparam1(default1), mparam2(default2), mparam3(default3) {} 
    ComplicatedParams &param1(P1 p) { mparam1 = p; return *this; } 
    ComplicatedParams &param2(P2 p) { mparam2 = p; return *this; } 
    ComplicatedParams &param3(P3 p) { mparam3 = p; return *this; } 
}; 

complicated_function(const ComplicatedParams &params); 

अब मैं इसे कॉल कर सकते हैं:

complicated_function(ComplicatedParams().param2(foo).param1(bar)); 

फोन करने वाले मापदंडों के आदेश को याद करने की जरूरत नहीं है जिसका मतलब है ।बिना विधि श्रृंखलन होगा होने के लिए:

ComplicatedParams params; 
params.param1(foo); 
params.param2(bar); 
complicated_function(params); 

मैं भी कॉल कर सकते हैं:

complicated_function(ComplicatedParams().param3(baz)); 

कि भार के की एक टन को परिभाषित करने के बिना, मैं सिर्फ पिछले पैरामीटर निर्दिष्ट कर सकते हैं और इसका मतलब है डिफ़ॉल्ट रूप से बाकी छोड़ दें।

अंतिम स्पष्ट ट्वीक complicated_functionComplicatedParams के एक सदस्य बनाने के लिए है:

struct ComplicatedAction { 
    P1 mparam1; 
    P2 mparam2; 
    P3 mparam3; 
    ComplicatedAction() : mparam1(default1), mparam2(default2), mparam3(default3) {} 
    ComplicatedAction &param1(P1 p) { mparam1 = p; return *this; } 
    ComplicatedAction &param2(P2 p) { mparam2 = p; return *this; } 
    ComplicatedAction &param3(P3 p) { mparam3 = p; return *this; } 
    run(void); 
}; 

ComplicatedAction().param3(baz).run(); 
संबंधित मुद्दे