कोई व्यक्ति प्रकाशन / सदस्यता पैटर्न (JS / jQuery में) का उपयोग क्यों करेगा?


103

इसलिए, एक सहकर्मी ने मुझे प्रकाशित / सदस्यता पैटर्न (JS / jQuery में) के लिए पेश किया, लेकिन मुझे एक कठिन समय मिल रहा है कि कोई इस पैटर्न का उपयोग 'सामान्य' जावास्क्रिप्ट / jQuery से अधिक क्यों करेगा।

उदाहरण के लिए, पहले मेरे पास निम्नलिखित कोड था ...

$container.on('click', '.remove_order', function(event) {
    event.preventDefault();
    var orders = $(this).parents('form:first').find('div.order');
    if (orders.length > 2) {
        orders.last().remove();
    }
});

और मैं इसके बजाय ऐसा करने की योग्यता देख सकता था, उदाहरण के लिए ...

removeOrder = function(orders) {
    if (orders.length > 2) {
        orders.last().remove();
    }
}

$container.on('click', '.remove_order', function(event) {
    event.preventDefault();
    removeOrder($(this).parents('form:first').find('div.order'));
});

क्योंकि यह removeOrderविभिन्न घटनाओं आदि के लिए कार्यक्षमता को फिर से उपयोग करने की क्षमता का परिचय देता है ।

लेकिन आप प्रकाशित / सदस्यता पैटर्न को लागू करने और निम्नलिखित लंबाई पर जाने का निर्णय क्यों करेंगे, अगर यह एक ही बात करता है? (FYI करें, मैंने jQuery छोटे पब / उप का उपयोग किया )

removeOrder = function(e, orders) {
    if (orders.length > 2) {
        orders.last().remove();
    }
}

$.subscribe('iquery/action/remove-order', removeOrder);

$container.on('click', '.remove_order', function(event) {
    event.preventDefault();
    $.publish('iquery/action/remove-order', $(this).parents('form:first').find('div.order'));
});

मैंने निश्चित रूप से पैटर्न के बारे में पढ़ा है, लेकिन मैं अभी कल्पना नहीं कर सकता कि यह कभी क्यों आवश्यक होगा। मैंने जो ट्यूटोरियल देखे हैं, वे बताते हैं कि इस पैटर्न को कैसे लागू किया जाए, केवल मूल उदाहरणों को ही कवर करें।

मुझे लगता है कि पब / उप की उपयोगिता एक अधिक जटिल अनुप्रयोग में खुद को स्पष्ट कर देगी, लेकिन मैं एक कल्पना नहीं कर सकता। मुझे डर है कि मैं बिंदु को पूरी तरह से याद कर रहा हूं; लेकिन अगर एक है तो मैं यह जानना चाहूंगा!

क्या आप स्पष्ट रूप से समझा सकते हैं कि यह पैटर्न क्यों और किन स्थितियों में फायदेमंद है? क्या यह कोड स्निपेट के लिए पब / उप पैटर्न का उपयोग करने के लायक है, जैसे मेरे उदाहरण ऊपर?

जवाबों:


222

यह सब ढीले युग्मन और एकल जिम्मेदारी के बारे में है, जो जावास्क्रिप्ट में एमवी * (एमवीसी / एमवीपी / एमवीवीएम) पैटर्न के साथ हाथ में जाता है जो पिछले कुछ वर्षों में बहुत आधुनिक हैं।

ढीला युग्मन एक वस्तु-उन्मुख सिद्धांत है जिसमें सिस्टम का प्रत्येक घटक अपनी जिम्मेदारी जानता है और अन्य घटकों के बारे में परवाह नहीं करता है (या कम से कम उनके बारे में अधिक से अधिक परवाह नहीं करने की कोशिश करता है)। ढीली युग्मन एक अच्छी बात है क्योंकि आप आसानी से विभिन्न मॉड्यूल का पुन: उपयोग कर सकते हैं। आप अन्य मॉड्यूल के इंटरफेस के साथ युग्मित नहीं हैं। प्रकाशन / सदस्यता का उपयोग करके आप केवल प्रकाशित / सदस्यता इंटरफ़ेस के साथ युग्मित होते हैं जो कि एक बड़ी बात नहीं है - सिर्फ दो तरीके। इसलिए यदि आप एक अलग परियोजना में एक मॉड्यूल का पुन: उपयोग करने का निर्णय लेते हैं तो आप इसे कॉपी और पेस्ट कर सकते हैं और यह संभवतः काम करेगा या कम से कम आपको इसे काम करने के लिए बहुत प्रयास की आवश्यकता नहीं होगी।

ढीली युग्मन के बारे में बात करते समय हमें चिंताओं के अलगाव का उल्लेख करना चाहिए। यदि आप एक एमवी * वास्तुशिल्प पैटर्न का उपयोग करके एक एप्लिकेशन का निर्माण कर रहे हैं तो आपके पास हमेशा एक मॉडल (एस) और एक दृश्य (एस) होता है। मॉडल आवेदन का व्यावसायिक हिस्सा है। आप इसे विभिन्न अनुप्रयोगों में पुन: उपयोग कर सकते हैं, इसलिए इसे किसी एकल एप्लिकेशन के दृश्य के साथ युगल करना अच्छा नहीं है, जहां आप इसे दिखाना चाहते हैं, क्योंकि आमतौर पर विभिन्न अनुप्रयोगों में आपके अलग-अलग विचार होते हैं। इसलिए मॉडल-व्यू संचार के लिए प्रकाशित / सदस्यता का उपयोग करना एक अच्छा विचार है। जब आपका मॉडल बदलता है तो यह एक घटना प्रकाशित करता है, दृश्य इसे पकड़ता है और खुद को अपडेट करता है। आपके पास प्रकाशित / सदस्यता से कोई उपरि नहीं है, यह आपको डिकॉउलिंग के लिए मदद करता है। उसी तरह से आप अपने एप्लिकेशन लॉजिक को उदाहरण के लिए कंट्रोलर (MVVM, MVP, यह बिल्कुल कंट्रोलर नहीं है) में रख सकते हैं और व्यू को यथासंभव सरल रखें। जब आपका दृश्य बदलता है (या उपयोगकर्ता किसी चीज़ पर क्लिक करता है, उदाहरण के लिए) यह सिर्फ एक नई घटना प्रकाशित करता है, तो नियंत्रक इसे पकड़ता है और निर्णय लेता है कि क्या करना है। यदि आप परिचित हैंMVC पैटर्न या Microsoft प्रौद्योगिकियों (WPF / सिल्वरलाइट) में MVVM के साथ आप ऑब्जर्वर पैटर्न की तरह प्रकाशित / सदस्यता के बारे में सोच सकते हैं । इस दृष्टिकोण का उपयोग Backbone.js, Knockout.js (MVVM) जैसे चौखटे में किया जाता है।

यहाँ एक उदाहरण है:

//Model
function Book(name, isbn) {
    this.name = name;
    this.isbn = isbn;
}

function BookCollection(books) {
    this.books = books;
}

BookCollection.prototype.addBook = function (book) {
    this.books.push(book);
    $.publish('book-added', book);
    return book;
}

BookCollection.prototype.removeBook = function (book) {
   var removed;
   if (typeof book === 'number') {
       removed = this.books.splice(book, 1);
   }
   for (var i = 0; i < this.books.length; i += 1) {
      if (this.books[i] === book) {
          removed = this.books.splice(i, 1);
      }
   }
   $.publish('book-removed', removed);
   return removed;
}

//View
var BookListView = (function () {

   function removeBook(book) {
      $('#' + book.isbn).remove();
   }

   function addBook(book) {
      $('#bookList').append('<div id="' + book.isbn + '">' + book.name + '</div>');
   }

   return {
      init: function () {
         $.subscribe('book-removed', removeBook);
         $.subscribe('book-aded', addBook);
      }
   }
}());

एक और उदाहरण। यदि आप MV * दृष्टिकोण को पसंद नहीं करते हैं, तो आप कुछ अलग उपयोग कर सकते हैं (वहाँ एक चौराहे के बीच है जिसका मैं अगले और अंतिम उल्लेख करूंगा)। बस अपने एप्लिकेशन को अलग-अलग मॉड्यूल में स्ट्रक्चर करें। उदाहरण के लिए ट्विटर पर देखें।

ट्विटर मॉड्यूल

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

यहाँ अंतिम दृष्टिकोण का एक मूल उदाहरण है (यह मूल ट्विटर कोड नहीं है यह मेरे द्वारा सिर्फ एक नमूना है):

var Twitter.Timeline = (function () {
   var tweets = [];
   function publishTweet(tweet) {
      tweets.push(tweet);
      //publishing the tweet
   };
   return {
      init: function () {
         $.subscribe('tweet-posted', function (data) {
             publishTweet(data);
         });
      }
   };
}());


var Twitter.TweetPoster = (function () {
   return {
       init: function () {
           $('#postTweet').bind('click', function () {
               var tweet = $('#tweetInput').val();
               $.publish('tweet-posted', tweet);
           });
       }
   };
}());

इस दृष्टिकोण के लिए निकोलस ज़कस द्वारा एक उत्कृष्ट बातचीत है । MV के लिए * सबसे अच्छे लेख और पुस्तकें जो मुझे पता हैं कि Addy Osmani द्वारा प्रकाशित हैं ।

कमियां: आपको प्रकाशन / सदस्यता के अत्यधिक उपयोग के बारे में सावधान रहना होगा। यदि आपको सैकड़ों ईवेंट मिले हैं, तो यह उन सभी को प्रबंधित करने के लिए बहुत भ्रमित हो सकता है। यदि आप नेमस्पेसिंग का उपयोग नहीं कर रहे हैं (या इसे सही तरीके से उपयोग नहीं कर रहे हैं) तो आपके पास टक्कर भी हो सकती है। मध्यस्थ का एक उन्नत कार्यान्वयन जो एक प्रकाशन / सदस्यता की तरह दिखता है, https://github.com/ajacksified/Mediator.js यहाँ पाया जा सकता है । इसमें नामकरण और घटना "बुदबुदाहट" जैसी विशेषताएं हैं, जो निश्चित रूप से बाधित हो सकती हैं। पब्लिश / सब्सक्राइब का एक और दोष हार्ड यूनिट टेस्टिंग है, मॉड्यूल में विभिन्न कार्यों को अलग करना और उन्हें स्वतंत्र रूप से परीक्षण करना मुश्किल हो सकता है।


3
धन्यवाद, यह समझ में आता है। मैं MVC पैटर्न से परिचित हूं क्योंकि मैं इसका हर समय PHP के साथ उपयोग करता हूं, लेकिन मैंने इवेंट-संचालित प्रोग्रामिंग के संदर्भ में इसके बारे में नहीं सोचा था। :)
मैककाथ

2
इस विवरण के लिए धन्यवाद। वास्तव में मुझे अवधारणा के चारों ओर अपना सिर लपेटने में मदद मिली।
फ्लाईबियर

1
यह एक उत्कृष्ट उत्तर है। इस मतदान से खुद को रोक नहीं पाए :)
नावेद बट्ट

1
महान व्याख्या, कई उदाहरण, आगे पढ़ने के सुझाव। A ++।
कार्सन

16

कोड के बीच युग्मन को कम करना मुख्य लक्ष्य है। यह सोचने का कुछ हद तक घटना-आधारित तरीका है, लेकिन "घटनाएँ" किसी विशिष्ट वस्तु से बंधी नहीं हैं।

मैं कुछ छद्म कोड में नीचे एक बड़ा उदाहरण लिखूंगा जो जावास्क्रिप्ट की तरह दिखता है।

मान लीजिए कि हमारे पास एक क्लास रेडियो और एक क्लास रिले है:

class Relay {
    function RelaySignal(signal) {
        //do something we don't care about right now
    }
}

class Radio {
    function ReceiveSignal(signal) {
        //how do I send this signal to other relays?
    }
}

जब भी रेडियो को सिग्नल मिलता है, हम संदेश को किसी तरह से रिले करने के लिए कई रिले चाहते हैं। रिले की संख्या और प्रकार भिन्न हो सकते हैं। हम इसे इस तरह से कर सकते हैं:

class Radio {
    var relayList = [];

    function AddRelay(relay) {
        relayList.add(relay);
    }

    function ReceiveSignal(signal) {
        for(relay in relayList) {
            relay.Relay(signal);
        }
    }

}

यह ठीक काम करता है। लेकिन अब कल्पना कीजिए कि हम एक अलग घटक चाहते हैं जो उन संकेतों का भी हिस्सा ले जो रेडियो वर्ग को प्राप्त होते हैं, अर्थात स्पीकर्स:

(क्षमा करें यदि उपमा शीर्ष पायदान पर नहीं हैं ...)

class Speakers {
    function PlaySignal(signal) {
        //do something with the signal to create sounds
    }
}

हम पैटर्न को फिर से दोहरा सकते हैं:

class Radio {
    var relayList = [];
    var speakerList = [];

    function AddRelay(relay) {
        relayList.add(relay);
    }

    function AddSpeaker(speaker) {
        speakerList.add(speaker)
    }

    function ReceiveSignal(signal) {

        for(relay in relayList) {
            relay.Relay(signal);
        }

        for(speaker in speakerList) {
            speaker.PlaySignal(signal);
        }

    }

}

हम "सिग्नल लिस्टनर" की तरह एक इंटरफ़ेस बनाकर इसे और बेहतर बना सकते हैं, ताकि हमें केवल रेडियो क्लास में एक सूची की आवश्यकता हो, और हमेशा उसी फ़ंक्शन को कॉल कर सकें जो भी वस्तु हमारे पास है जो सिग्नल को सुनना चाहता है। लेकिन अभी भी जो भी इंटरफेस / बेस क्लास / आदि हम और रेडियो वर्ग तय करते हैं उसके बीच एक युग्मन बनता है। मूल रूप से जब भी आप रेडियो, सिग्नल या रिले वर्ग में से किसी एक को बदलते हैं, तो आपको यह सोचना होगा कि यह संभवतः अन्य दो वर्गों को कैसे प्रभावित कर सकता है।

अब कुछ अलग करने की कोशिश करते हैं। चलिए RadioMast नाम का एक चौथा वर्ग बनाते हैं:

class RadioMast {

    var receivers = [];

    //this is the "subscribe"
    function RegisterReceivers(signaltype, receiverMethod) {
        //if no list for this type of signal exits, create it
        if(receivers[signaltype] == null) {
            receivers[signaltype] = [];
        }
        //add a subscriber to this signal type
        receivers[signaltype].add(receiverMethod);
    }

    //this is the "publish"
    function Broadcast(signaltype, signal) {
        //loop through all receivers for this type of signal
        //and call them with the signal
        for(receiverMethod in receivers[signaltype]) {
            receiverMethod(signal);
        }
    }
}

अब हमारे पास एक ऐसा पैटर्न है जिसके बारे में हम जानते हैं और जब तक वे किसी भी संख्या और वर्गों के प्रकारों के लिए उपयोग कर सकते हैं:

  • RadioMast के बारे में जानते हैं (सभी संदेश पास करने वाला वर्ग)
  • संदेश भेजने / प्राप्त करने के लिए विधि हस्ताक्षर के बारे में जानते हैं

इसलिए हम रेडियो क्लास को उसके अंतिम, सरल रूप में बदलते हैं:

class Radio {
    function ReceiveSignal(signal) {
        RadioMast.Broadcast("specialradiosignal", signal);
    }
}

और हम इस प्रकार के सिग्नल के लिए रेडियोमास्ट की रिसीवर सूची में स्पीकर और रिले जोड़ते हैं:

RadioMast.RegisterReceivers("specialradiosignal", speakers.PlaySignal);
RadioMast.RegisterReceivers("specialradiosignal", relay.RelaySignal);

अब स्पीकर्स और रिले क्लास को किसी भी चीज़ का शून्य ज्ञान है, सिवाय इसके कि उनके पास एक ऐसा तरीका हो जो सिग्नल प्राप्त कर सके, और रेडियो क्लास, प्रकाशक होने के नाते, रेडियोमास्ट से अवगत है कि वह सिग्नलों को प्रकाशित करता है। यह संदेश-पास करने वाली प्रणाली जैसे प्रकाशन / सदस्यता का उपयोग करने का बिंदु है।


वास्तव में महान एक ठोस उदाहरण है जो दर्शाता है कि पब / उप पैटर्न को लागू करना 'सामान्य' तरीकों का उपयोग करने से बेहतर कैसे हो सकता है! धन्यवाद!
मकाकथ

1
आपका स्वागत है! व्यक्तिगत रूप से मुझे अक्सर लगता है कि जब तक मुझे एक वास्तविक समस्या का एहसास नहीं होता है, तब तक मेरा मस्तिष्क 'क्लिक' नहीं करता है, जब तक कि यह एक वास्तविक समस्या नहीं है। उप / पब पैटर्न उन आर्किटेक्चर के साथ बहुत अच्छा है जो वैचारिक रूप से कसकर युग्मित हैं, लेकिन हम अभी भी उन्हें यथासंभव अलग रखना चाहते हैं। एक ऐसे खेल की कल्पना करें जहां आपके पास सैकड़ों वस्तुएं हैं जो सभी को उदाहरण के लिए उनके आसपास होने वाली चीजों पर प्रतिक्रिया करनी है, और ये वस्तुएं सब कुछ हो सकती हैं: खिलाड़ी, बुलेट, पेड़, ज्यामिति, गुई इत्यादि
एंडर्स अरपी

3
जावास्क्रिप्ट में classकीवर्ड नहीं है । कृपया इस तथ्य पर जोर दें, जैसे। अपने कोड को छद्म कोड के रूप में वर्गीकृत करके।
रोब डब्ल्यू

दरअसल ES6 में एक क्लास कीवर्ड है।
मिन्को गॉशेव

5

अन्य उत्तरों ने यह दिखाने में बहुत अच्छा काम किया है कि पैटर्न कैसे काम करता है। मैं निहित प्रश्न को संबोधित करना चाहता था " पुराने तरीके से क्या गलत है? " जैसा कि मैं हाल ही में इस पैटर्न के साथ काम कर रहा हूं, और मुझे लगता है कि इसमें मेरी सोच में बदलाव शामिल है।

कल्पना कीजिए कि हमने एक आर्थिक बुलेटिन की सदस्यता ली है। बुलेटिन एक शीर्षक प्रकाशित करता है: " 200 बिंदुओं से डाउ जोन्स कम करें "। यह भेजने के लिए एक अजीब और कुछ गैर जिम्मेदाराना संदेश होगा। यदि फिर भी, यह प्रकाशित हुआ: " एनरॉन ने आज सुबह अध्याय 11 बैंक संरक्षण के लिए दायर किया ", तो यह एक अधिक उपयोगी संदेश है। ध्यान दें कि संदेश डॉव जोन्स के 200 अंक गिर सकता है , लेकिन यह एक और मामला है।

एक कमांड भेजने और कुछ ऐसा करने की सलाह देने के बीच अंतर है। इसे ध्यान में रखते हुए, पब / उप पैटर्न के अपने मूल संस्करण को लें, अब के लिए हैंडलर को अनदेखा करें:

$.subscribe('iquery/action/remove-order', removeOrder);

$container.on('click', '.remove_order', function(event) {
    event.preventDefault();
    $.publish('iquery/action/remove-order', $(this).parents('form:first').find('div.order'));
});

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

$.subscribe('iquery/action/remove-order-requested', handleRemoveOrderRequest);

$container.on('click', '.remove_order', function(event) {
    event.preventDefault();
    $.publish('iquery/action/remove-order-requested', $(this).parents('form:first').find('div.order'));
});

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

handleRemoveOrderRequest = function(e, orders) {
    logAction(e, "remove order requested");
    if( !isUserLoggedIn()) {
        adviseUser("You need to be logged in to remove orders");
    } else if (isOkToRemoveOrders(orders)) {
        orders.last().remove();
        adviseUser("Your last order has been removed");
        logAction(e, "order removed OK");
    } else {
        adviseUser("Your order was not removed");
        logAction(e, "order not removed");
    }
    remindUserToFloss();
    increaseProgrammerBrowniePoints();
    //etc...
}

एक कमांड और एक अधिसूचना के बीच अंतर इस पैटर्न के साथ बनाने के लिए एक उपयोगी अंतर है, IMO।


यदि आपके पिछले 2 फ़ंक्शन ( remindUserToFloss& increaseProgrammerBrowniePoints) अलग-अलग मॉड्यूल में स्थित थे, तो क्या आप 2 घटनाओं को एक-दूसरे के ठीक बाद में प्रकाशित handleRemoveOrderRequestकरेंगे या क्या आपके पास flossModuleकिसी browniePointsमॉड्यूल के लिए एक ईवेंट प्रकाशित होने पर होगा remindUserToFloss()?
ब्रायन पी।

4

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

विकिपीडिया द्वारा उल्लिखित युग्मन के कुछ नुकसान हैं

कसकर युग्मित प्रणालियां निम्नलिखित विकासात्मक विशेषताओं का प्रदर्शन करती हैं, जिन्हें अक्सर नुकसान के रूप में देखा जाता है:

  1. एक मॉड्यूल में परिवर्तन आमतौर पर अन्य मॉड्यूल में परिवर्तन के एक लहर प्रभाव को मजबूर करता है।
  2. मॉड्यूल की असेंबली को अधिक अंतर-मॉड्यूल निर्भरता के कारण अधिक प्रयास और / या समय की आवश्यकता हो सकती है।
  3. एक विशेष मॉड्यूल का पुन: उपयोग और / या परीक्षण करना कठिन हो सकता है क्योंकि निर्भर मॉड्यूल को शामिल किया जाना चाहिए।

व्यावसायिक डेटा एन्कैप्सुलेटिंग ऑब्जेक्ट जैसी किसी चीज़ पर विचार करें। जब भी उम्र निर्धारित की जाती है, तो पृष्ठ को अपडेट करने के लिए इसमें हार्ड कोडित विधि कॉल होती है:

var person = {
    name: "John",
    age: 23,

    setAge: function( age ) {
        this.age = age;
        showAge( age );
    }
};

//Different module

function showAge( age ) {
    $("#age").text( age );
}

अब मैं showAgeफ़ंक्शन सहित व्यक्ति ऑब्जेक्ट का परीक्षण भी नहीं कर सकता । इसके अलावा, अगर मुझे कुछ अन्य जीयूआई मॉड्यूल में उम्र दिखाने की आवश्यकता है, तो मुझे उस पद्धति को कॉल करने के लिए हार्डकोड करने की आवश्यकता है .setAge, और अब व्यक्ति ऑब्जेक्ट में 2 असंबंधित मॉड्यूल के लिए निर्भरता है। जब आप कॉल करते हैं, तो उन्हें बनाए रखना मुश्किल होता है और वे एक ही फ़ाइल में भी नहीं होते हैं।

ध्यान दें कि एक ही मॉड्यूल के अंदर, आप निश्चित रूप से प्रत्यक्ष विधि कॉल कर सकते हैं। लेकिन व्यावसायिक डेटा और सतही गुई व्यवहार किसी भी उचित मानकों द्वारा एक ही मॉड्यूल में नहीं रहना चाहिए।


मैं यहाँ 'निर्भरता' की अवधारणा को नहीं समझता; मेरे दूसरे उदाहरण में निर्भरता कहां है, और यह मेरे तीसरे से कहां गायब है? मैं अपने दूसरे और तीसरे स्निपेट के बीच कोई व्यावहारिक अंतर नहीं देख सकता - यह सिर्फ एक वास्तविक कारण के बिना फ़ंक्शन और घटना के बीच एक नई 'परत' को जोड़ने के लिए लगता है। मैं शायद अंधा हो रहा हूं, लेकिन मुझे लगता है कि मुझे और अधिक संकेत की आवश्यकता है। :(
मैककथ

1
क्या आप एक नमूना उपयोग का मामला प्रदान कर सकते हैं जहां प्रकाशित / सदस्यता केवल एक फ़ंक्शन बनाने से अधिक उपयुक्त होगा जो एक ही कार्य करता है?
जेफरी स्वीनी

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

जबकि मुझे अभी भी लगता है कि आपके द्वारा यहां वर्णित के बारे में जाने के बेहतर तरीके हैं, मुझे कम से कम यकीन है कि इस पद्धति का उद्देश्य है, खासकर अन्य डेवलपर्स के साथ वातावरण में। +1
जेफरी स्वीनी

1
@Esailija - धन्यवाद, मुझे लगता है कि मैं थोड़ा बेहतर समझता हूं। इसलिए ... अगर मैंने ग्राहक को पूरी तरह से हटा दिया, तो यह त्रुटि या कुछ भी नहीं होगा, यह सिर्फ कुछ नहीं करेगा? और क्या आप कहेंगे कि यह उस मामले में उपयोगी हो सकता है, जहाँ आप कोई कार्य करना चाहते हैं, लेकिन जरूरी नहीं कि प्रकाशन के समय कौन सा कार्य सबसे अधिक प्रासंगिक हो, लेकिन ग्राहक अन्य कारकों के आधार पर बदल सकता है?
मकाकथ

1

PubSub कार्यान्वयन आमतौर पर वहां देखा जाता है जहां -

  1. कार्यान्वयन की तरह एक पोर्टलेट है जहां कई पोर्टल्स हैं जो एक इवेंट बस की मदद से संवाद करते हैं। यह aync आर्किटेक्चर बनाने में मदद करता है।
  2. चुस्त युग्मन द्वारा तैयार प्रणाली में, पबसूब एक तंत्र है जो विभिन्न मॉड्यूल के बीच संचार करने में मदद करता है।

उदाहरण कोड -

var pubSub = {};
(function(q) {

  var messages = [];

  q.subscribe = function(message, fn) {
    if (!messages[message]) {
      messages[message] = [];
    }
    messages[message].push(fn);
  }

  q.publish = function(message) {
    /* fetch all the subscribers and execute*/
    if (!messages[message]) {
      return false;
    } else {
      for (var message in messages) {
        for (var idx = 0; idx < messages[message].length; idx++) {
          if (messages[message][idx])
            messages[message][idx]();
        }
      }
    }
  }
})(pubSub);

pubSub.subscribe("event-A", function() {
  console.log('this is A');
});

pubSub.subscribe("event-A", function() {
  console.log('booyeah A');
});

pubSub.publish("event-A"); //executes the methods.

1

पेपर "द कई फेसेस ऑफ पब्लिश / सब्सक्राइब" एक अच्छी रीड है और एक बात जो वे जोर देते हैं वह तीन "आयामों" में डिकॉप्लिंग है। यहाँ मेरा कच्चा सारांश है, लेकिन कृपया कागज को भी देखें।

  1. अंतरिक्ष की कटाई। बातचीत करने वाले दलों को एक-दूसरे को जानने की जरूरत नहीं है। प्रकाशक को पता नहीं है कि कौन सुन रहा है, कितने सुन रहा है, या वे घटना के साथ क्या कर रहे हैं। ग्राहकों को यह नहीं पता है कि इन घटनाओं का उत्पादन कौन कर रहा है, कितने निर्माता हैं आदि।
  2. समय की कमी। बातचीत के दौरान बातचीत करने वाले दलों को एक ही समय में सक्रिय होने की आवश्यकता नहीं है। उदाहरण के लिए, एक प्रकाशक द्वारा कुछ घटनाओं को प्रकाशित करने के दौरान एक ग्राहक को डिस्कनेक्ट किया जा सकता है, लेकिन यह ऑनलाइन आने पर इस पर प्रतिक्रिया कर सकता है।
  3. तुल्यकालन decoupling। जब भी आयोजनों के लिए उनके द्वारा प्रस्तुत की जाने वाली घटना को कॉलबैक के माध्यम से प्रकाशकों को असिंक्रोनस रूप से अधिसूचित किया जा सकता है, तो उन्हें ब्लॉक नहीं किया जाता है।

0

सरल उत्तर मूल प्रश्न एक सरल उत्तर की तलाश में था। यहाँ मेरा प्रयास है।

जावास्क्रिप्ट कोड ऑब्जेक्ट्स के लिए अपनी स्वयं की घटनाओं को बनाने के लिए कोई तंत्र प्रदान नहीं करता है। इसलिए आपको एक प्रकार के इवेंट तंत्र की आवश्यकता है। प्रकाशित / सदस्यता पैटर्न इस आवश्यकता का जवाब देगा, और यह आपके लिए एक ऐसा तंत्र चुनने के लिए है जो आपकी अपनी आवश्यकताओं के लिए सबसे उपयुक्त है।

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

इसलिए विरोधाभासी रूप से, अधिक कोड चिंताओं का एक बेहतर पृथक्करण बनाता है, जो बहुत जटिल वेब पृष्ठों तक अच्छी तरह से लागू होता है।

मुझे आशा है कि किसी को विस्तार से जाने के बिना यह एक अच्छी चर्चा मिल सकती है।

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