पर्यवेक्षक पैटर्न; * क्या बदल रहा है?


10

मैंने दो एब्स्ट्रैक्ट क्लासेज सब्जेक्ट और ऑब्जर्वर बनाए हैं जो एक क्लासिक ऑब्जर्वर पैटर्न इंटरफ़ेस को परिभाषित करते हैं। मैं ऑब्जर्वर पैटर्न को लागू करने के लिए उनसे प्राप्त करता हूं। एक पर्यवेक्षक इस तरह दिख सकता है:

void MyClass::Update(Subject *subject)
{
    if(subject == myService_)
    {
        DoSomething();
    }
    else if(subject == myOtherService_)
    {
        DoSomethingElse();
    }
}

यह ठीक है और यह मुझे बताता है कि किसने कुछ बदला। हालाँकि, यह मुझे नहीं बताता कि क्या बदला। कभी-कभी यह ठीक है क्योंकि मैं केवल नवीनतम डेटा के लिए विषय को क्वेरी करने जा रहा हूं, लेकिन अन्य बार मुझे यह जानना होगा कि वास्तव में विषय में क्या बदलाव हुआ है। मुझे लगता है कि वे जावा में सूचना देते हैं कि दोनों के पास एक InformObservers () विधि और एक InformObservers (ऑब्जेक्ट arg) विधि है जो संभवतः बदले हुए विवरणों को निर्दिष्ट करता है।

मेरे मामले में मुझे यह जानने की आवश्यकता है कि क्या किसी एक जोड़े के विषय पर अलग-अलग कार्रवाई हुई है और यदि यह एक विशेष कार्रवाई है, तो उस कार्रवाई से संबंधित पूर्णांक संख्या जानने के लिए।

तो मेरे सवाल हैं:

  1. एक सामान्य तर्क पारित करने के लिए C ++ तरीका क्या है (जैसा कि जावा करता है)?
  2. क्या प्रेक्षक भी सबसे अच्छा पैटर्न है? शायद किसी तरह का इवेंट सिस्टम?

अपडेट करें

मुझे यह लेख मिला जो ऑब्जर्वर पैटर्न को गति देने के बारे में बात करता है: टेम्पलेट्स के साथ एक विषय / प्रेक्षक पैटर्न को लागू करना । इससे मुझे आश्चर्य हुआ कि क्या आप किसी तर्क को खा सकते हैं।

मुझे यह स्टैक ओवरफ्लो प्रश्न मिला जो तर्क को गति देने के बारे में बात करता है: टेम्पलेट आधारित विषय ऑब्जर्वर पैटर्न - क्या मुझे static_cast या डायनामिक_का उपयोग करना चाहिए । हालांकि, ओपी के पास एक समस्या है जो किसी ने उत्तर नहीं दी है।

दूसरी चीज़ जो मैं कर सकता था वह है अपडेट विधि को एक EventArg ऑब्जेक्ट के रूप में बदलने के लिए:

void MyClass::Update(Subject *subject, EventArg arg)
{
  ...

और फिर विशेष तर्क डेटा के लिए EventArg के उप-वर्ग बनाएं, और फिर मुझे लगता है कि इसे अपडेट विधि के भीतर विशिष्ट उपवर्ग में वापस डाल दिया जाए।

अद्यतन २

एक लेख भी मिला, अतुल्यकालिक संदेश-आधारित सी ++ फ्रेमवर्क बनाने पर; भाग 2 जिसमें विषय के बारे में चर्चा की गई है कि क्या बदला है।

अब मैं गंभीरता से Boost.Signals का उपयोग करने पर विचार कर रहा हूं । अपने स्वयं के पर्यवेक्षक पैटर्न का उपयोग करना समझ में आता है जब यह सरल था, लेकिन प्रकार और एक तर्क को गति देना जटिल होने लगा है। और मुझे Boost.Signals2 की थ्रेड सुरक्षा की आवश्यकता हो सकती है।

अद्यतन 3

मुझे पर्यवेक्षक पैटर्न पर कुछ दिलचस्प लेख भी मिले:

हर्ब सटर द्वारा ऑब्जर्वर को सामान्य बनाना

C ++ - 1 भाग में ऑब्जर्वर पैटर्न को लागू करना

प्रेक्षक के डिजाइन पैटर्न को लागू करने के अनुभव (भाग 2)

प्रेक्षक के डिजाइन पैटर्न को लागू करने के अनुभव (भाग 3)

हालाँकि, मैंने अपने कार्यान्वयन को Boost.Signals के उपयोग से बंद कर दिया है, जबकि संभवतः मेरे उद्देश्यों के लिए फूला हुआ, सफलतापूर्वक काम कर रहा है। और शायद ब्लोट या गति की कोई भी चिंता अप्रासंगिक है।


शरीर के प्रश्न वास्तव में आपके शीर्षक से मेल नहीं खाते हैं। वास्तव में प्रश्न का मूल क्या है?
निकोल

@ संदर्भ: मैं वर्तमान में अपने पोस्ट की शुरुआत में कोड नमूने के रूप में ऑब्जर्वर पैटर्न का उपयोग कर रहा हूं। वर्तमान में मैं जिस कोड पर काम कर रहा हूं, उसके लिए यह पता चला है कि मुझे विशेष रूप से यह जानने की जरूरत है कि मैं किस तरह से बदल सकता हूं। पर्यवेक्षक पैटर्न का मेरा वर्तमान कार्यान्वयन (जो मानक एक है) यह जानकारी प्रदान नहीं करता है। मेरा सवाल यह है कि सबसे अच्छा कैसे बदला के बारे में जानकारी प्राप्त करने के लिए है।
उपयोगकर्ता

@Renesis: यहाँ एक मंच धागा है जो मेरा एक समान सवाल पूछ रहा है: gamedev.net/topic/497105-observer-pattern
उपयोगकर्ता

विज्ञापन अपडेट 2: मैं निश्चित रूप से Boost.Signals का उपयोग कर समर्थन करता हूं। यह अपने आप को रोल करने की तुलना में बहुत अधिक सुविधाजनक है। Libsigc ++ भी है अगर आप इस कार्य के लिए कुछ हल्का-वजन चाहते थे (Boost.Signals बाकी Boost से बहुत सारे कोड का उपयोग करता है); हालांकि यह थ्रेड-सेफ नहीं है।
Jan Hudec

गति के मुद्दों के बारे में: मुझे विशेष रूप से पता नहीं है कि बूस्ट.सिग्नल कितना तेज़ है, लेकिन यह केवल एक चिंता का विषय है जब आपके पास बड़ी मात्रा में घटनाएँ होती हैं ...
Max

जवाबों:


4

क्या C ++ या JAVA, प्रेक्षक के लिए एक अधिसूचना क्या बदल गया है की जानकारी के साथ आ सकता है। एक ही तरीके InformObservers (ऑब्जेक्ट arg) का उपयोग C ++ में भी किया जा सकता है।

आम तौर पर, मुद्दा यह रहेगा कि एक या कई पर्यवेक्षकों को भेजने वाले कई विषय हो सकते हैं और इसलिए, class argहार्ड कोड नहीं किया जा सकता है।

आमतौर पर, करने का सबसे अच्छा तरीका जेनेरिक संदेश / टोकन के रूप में arg बनाना है जो विभिन्न वर्गों के लिए समान डेटा प्रकार बनाता है, लेकिन विभिन्न देखे गए वर्गों के लिए मान भिन्न होते हैं। वैकल्पिक रूप से, यदि इस तरह के सभी अधिसूचना मूल्य कुछ आधारित वर्ग पर कक्षा से बाहर हो जाते हैं जो सभी के लिए सामान्य है।

पर्यवेक्षक पैटर्न के लिए, यह है महत्वपूर्ण है कि Arg डेटा प्रकार कठिन observee और पर्यवेक्षक के बीच कोडित नहीं है - और यह एक युग्मन है कि चीजें विकसित करने के लिए कठिन बना देता है है।

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


5
पर्यवेक्षक तर्क समझता है, तो वहाँ है एक युग्मन, चाहे कितना आप प्रकार छिपाना। वास्तव में मैं यह कहना चाहते हैं और अधिक विकसित करने के लिए मुश्किल है, तो आप पारित Object( void *, boost::anyया कुछ इसी तरह सामान्य) यदि आप विशिष्ट प्रकार है, क्योंकि विशेष प्रकार आप संकलन समय है कि कुछ बदल गया पर देखेंगे के साथ है, जबकि सामान्य प्रकार के साथ पारित यह संकलन और काम करना बंद कर देगा, क्योंकि पर्यवेक्षक पास किए गए वास्तविक डेटा के साथ काम करने में सक्षम नहीं होगा।
Jan Hudec

@ जैनधुके: मैं इससे सहमत हूं, लेकिन क्या इसका मतलब है कि आप प्रत्येक तर्क के लिए एक विशिष्ट एक-ऑफ ऑब्जर्वर / विषय उपवर्ग सेट करें (यानी, प्रत्येक उपयोग के मामले के लिए)?
यूजर

@ जानहुडेक: कपलिंग भी केवल एक ही तरीका है। विषय का पर्यवेक्षकों के बारे में कोई पता नहीं है। हां पर्यवेक्षक विषय के बारे में जानता है, लेकिन क्या पर्यवेक्षक पैटर्न काम नहीं करता है?
यूजर

1
@ उपयोगकर्ता: हां, मैं प्रत्येक विषय के लिए एक विशिष्ट इंटरफ़ेस बनाता हूं और प्रत्येक पर्यवेक्षक उन विषयों के इंटरफेस को लागू करता है, जिन्हें इसे देखने की आवश्यकता है। खैर, मैं जिन भाषाओं का उपयोग करता हूं, उनके पास भाषा या फ्रेमवर्क (C # डेलीगेट्स, C ++ 11 std::functionबूस्ट boost::function, Gtk + GClosure, पायथन बाउंड मैथड्स आदि) में बाध्य विधि बिंदु होते हैं , इसलिए मैं सिर्फ उचित हस्ताक्षर वाले तरीकों को परिभाषित करता हूं और वास्तविक बनाने के लिए सिस्टम से पूछता हूं। देखने वाला। युग्मन वास्तव में सिर्फ एक तरीका है, विषय पर्यवेक्षकों के लिए इंटरफ़ेस को परिभाषित करता है, लेकिन उनके कार्यान्वयन के बारे में विचार नहीं है।
Jan Hudec

0

C ++ में "जावा लाइक" जेनेरिक ईवेंट तर्क भेजने के कुछ तरीके हैं।

1) घटना के तर्क को शून्य * घोषित करें और इसे इवेंट हैंडलर में सही वर्ग के लिए भेजें।

2) घटना तर्क को एक नए वर्ग / इंटरफ़ेस के लिए पॉइंटर / रेफरी के रूप में घोषित करें (जैसे आपके उदाहरण के जवाब में)

class GenericEventArgument
{
  virtual bool didAction1Happen() = 0;
  virtual int getActionInteger() = 0;
};

और वास्तविक घटना तर्क कक्षाएं इस वर्ग से प्राप्त होती हैं।

जैसा कि आप के लिए एक टेम्पलेट आधारित पर्यवेक्षक की जाँच के बारे में सवाल

http://www.codeproject.com/Articles/3267/Implementing-a-Subject-Observer-pattern-with-templ


-1

मुझे नहीं पता कि यह विहित नाम है, लेकिन मेरे पुराने स्मॉलटाक दिनों से मुझे "पहलू" शब्द याद है कि पहचानने के लिए क्या बदल गया है।

यह EventArg के आपके विचार (और इसे उपवर्ग के रूप में) के रूप में जटिल नहीं है; यह केवल पर्यवेक्षक से पर्यवेक्षक के लिए एक स्ट्रिंग (एक पूर्णांक स्थिर भी हो सकता है) गुजरता है।

प्लस: बस दो सरल तरीके हैं ( update(observable)औरupdateAspect(observable, aspect)

माइनस: पर्यवेक्षक को आगे की जानकारी के लिए अवलोकन योग्य पूछना पड़ सकता है (जैसे, आपका "पूर्णांक संख्या")

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.