प्रेक्षक पैटर्न
सॉफ्टवेर प्रारूप और सॉफ्टवेयर रचना में प्रेक्षक प्रारूप एक सॉफ्टवेयर प्रारूप है जिसमें उद्देश्य उन्मुख कार्यक्रम में एक उद्देश्य कंप्यूटर विज्ञान होता है जिसे कम्प्यूटर विषय कहा जाता है जिसमें कम्प्यूटर अपने आश्रितों की एक सूची रखता है जिन्हें पर्यवेक्षक कहा जाता है और उन्हें स्वचालित रूप से सूचित करता है कि कोई भी घटना की गणना करने पर उनकी किसी विधि को कंप्यूटर विज्ञान के नाम से जाना जाता है।
इसका उपयोग अधिकतर घटना संचालित कार्यक्रम में घटना संचालित सॉफ्टवेयर में वितरित घटना से निपटना घटना सम्भालने की प्रणाली को लागू किया जाता है ऐसी प्रणालियों में विषय को आमतौर पर घटनाओं की धारा या घटनाओं को धारा स्रोत का नाम दिया जाता है जबकि पर्यवेक्षकों को घटनाओं का सिंक कहा जाता है धारा नामकरण एक भौतिक उत्पन्न की ओर संकेत करता है जिसमें पर्यवेक्षक भौतिक रूप से अलग हो जाते हैं और विषय/धारा स्रोत से उत्सर्जित घटनाओं पर उनका कोई नियंत्रण नहीं होता है यह प्रारूप इस प्रकार किसी भी प्रक्रिया के लिए उपयुक्त है जिसके द्वारा डेटा कुछ इनपुट से आता है जो बूटिंग पर CPU के लिए उपलब्ध नहीं है बल्कि इसके जगह यादृच्छिक रूप से यह आता है जैसे HTTP अनुरोध GPIO डेटा बाह्य उपकरणों से उपयोगकर्ता इनपुट वितरित डेटाबेस और ब्लॉकचेनआदि।
अधिकांश आधुनिक कार्यक्रमिक भाषाओं में पर्यवेक्षक प्रारूप घटकों को लागू करने वाले अंतर्निहित घटना निर्माण में सम्मिलित होते हैं जबकि यह अनिवार्य नहीं है अधिकांश पर्यवेक्षक कार्यान्वयन विषय की घटनाओं और कर्नेल द्वारा प्रदान किए गए अन्य समर्थन तंत्रों को सुनने के लिए गणना का उपयोग करते हैं।
अवलोकन
प्रेक्षक बनावट प्रारूप 23 प्रसिद्ध बनावट प्रारूप के बीच सूचीबद्ध एक व्यवहारिक प्रारूप है गैंग ऑफ़ फोर बनावट प्रारूप जो लचीले और पुन: प्रयोज्य प्रेक्षक उन्मुख सॉफ्टवेयर को प्रारूप में बदलने के लिए आवर्ती प्रारूप चुनौतियों का समाधान करते हैं ऐसा प्रेक्षक प्रदान करते हैं जिन्हें लागू करना, बदलना, परीक्षण करना और पुन: उपयोग करना आसान होता है।[1]
प्रेक्षक बनावट प्रारूप किन समस्याओं का समाधान कर सकता है
पर्यवेक्षक प्रारूप निम्नलिखित समस्याओं का समाधान करता है [2]
- वस्तुओं के बीच एक-से-अनेक निर्भरता को वस्तुओं को कसकर जोड़े बिना परिभाषित किया जाना चाहिए
- जब एक वस्तु स्थिति बदलती है तो आश्रित वस्तुओं की खुली और आखिरी संख्या को स्वचालित रूप से नवीनीकरण किया जाना चाहिए
- एक वस्तु कई अन्य वस्तुओं को सूचित कर सकती है
एक वस्तु विषय को परिभाषित करके वस्तुओं के बीच एक-से-अनेक निर्भरता को परिभाषित करना जो निर्भर वस्तुओं की स्थिति को अद्यतन करता है क्योंकि यह विषय को विशेष निर्भर वस्तुओं से जोड़ता है जबकि यह प्रदर्शन के दृष्टिकोण से लागू हो सकता है यदि प्रेक्षक कार्यान्वयन युग्मित है जैसे निम्न-स्तरीय कर्नेल संरचनाएं जो प्रति सेकंड हजारों बार निष्पादित होती हैं तो युग्मित वस्तुओं को कुछ परिदृश्यों में लागू करना जटिल हो सकता है और आसानी से पुन: उपयोग नहीं किया जाता है क्योंकि वे विभिन्न मिलनबिन्दु के साथ कई वस्तुओं को संदर्भित करते हैं और उनसे अवगत होते हैं अन्य परिदृश्यों में युग्मित प्रेक्षक एक बेहतर विकल्प हो सकते हैं क्योंकि संकलन समय पर त्रुटियों का पता लगाने और सीपीयू अनुदेश स्तर पर संकेत चिन्ह को अनुकूलित करने में सक्षम है।
प्रेक्षक बनावट प्रारूप किस समाधान का वर्णन करता है
- परिभाषित करना वस्तु और प्रेक्षक वस्तुएं
- जब कोई विषय स्थिति बदलता है तो सभी पंजीकृत पर्यवेक्षकों को स्वचालित रूप से और संभवतः अतुल्यकालिक रूप से सूचित और नवीनीकरण किया जाता है।
किसी विषय की एकमात्र ज़िम्मेदारी पर्यवेक्षकों की एक सूची बनाए रखना और उन्हें कॉल करके राज्य परिवर्तनों के बारे में सूचित करना है नवीनीकरण कार्यवाही पर्यवेक्षकों की ज़िम्मेदारी किसी विषय के साथ खुद को पंजीकृत और अपंजीकृत करना है राज्य परिवर्तनों के बारे में सूचित होने के लिए और अधिसूचित होने पर अपने राज्य को अद्यतन करना ही पने राज्य को विषय के राज्य के साथ सिंक्रनाइज़ करना होता है यह विषय पर्यवेक्षकों को शिथिल रूप से युग्मित बनाता है तथा विषय और पर्यवेक्षकों को एक दूसरे के बारे में कोई स्पष्ट ज्ञान नहीं है पर्यवेक्षकों को समय दौड़ पर स्वतंत्र रूप से जोड़ा और हटाया जा सकता है इस अधिसूचना-पंजीकरण परस्पर को प्रकाशित-सदस्यता के रूप में भी जाना जाता है।
मजबूत बनाम कमजोर संदर्भ
पर्यवेक्षक प्रारूप स्मृति रिसाव का कारण बन सकता है जिसे व्यपगत श्रोता समस्या के रूप में जाना जाता है बुनियादी कार्यान्वयन में इसे निपटान चिन्ह की तरह स्पष्ट पंजीकरण और स्पष्ट डी पंजीकरण दोनों की आवश्यकता होती है क्योंकि विषय पर्यवेक्षकों को संदर्भ में रखता है तथा उन्हें जीवित रखता है यदि विषय पर्यवेक्षकों के प्रति कमजोर संदर्भ रखता है तो इसे रोका जा सकता है।
युग्मन और विशिष्ट प्रकाशन-सदस्यता कार्यान्वयन
आमतौर पर पर्यवेक्षक प्रारूप को लागू किया जाता है जिससे देखा जा रहा विषय उस वस्तु का हिस्सा हो जिसके लिए राज्य परिवर्तन देखे जा रहे हैं और पर्यवेक्षकों को सूचित किया जाता है कि इस प्रकार के कार्यान्वयन को युग्मन कंप्यूटर प्रोग्रामिंग माना जाता है जो पर्यवेक्षकों और विषय दोनों को एक-दूसरे के बारे में जागरूक होने और उनके आंतरिक भागों तक पहुंचने के लिए मजबूत है जिससे मापनीयता गति, संदेश, पुनर्प्राप्ति और रखरखाव जिसे घटना भी कहा जाता है इसमें संभावित मुद्दे भी उत्तपन्न होते हैं अधिसूचना हानि फैलाव में लचीलेपन की कमी और वांछित सुरक्षा उपायों में संभावित बाधा प्रकाशन-सदस्यता प्रारूप के कुछ मतदान कंप्यूटर विज्ञान गैर-मतदान कार्यान्वयन में इसे पर्यवेक्षक और प्रेक्षक के बीच एक अतिरिक्त चरण के रूप में एक समर्पित संदेश पंक्ति सर्वर और कभी-कभी एक अतिरिक्त संदेश प्रेक्षक बनाकर हल किया जाता है तथा अवलोकन किया जाता है और इस प्रकार के घटकों को अलग किया जाता है इन जगहों में संदेश पंक्ति सर्वर को पर्यवेक्षक पैटर्न के साथ पर्यवेक्षकों द्वारा अभिगम किया जाता है जबकि संदेश भेजने वाले के बारे में कुछ भी नहीं जानते हैं प्रेषक को पर्यवेक्षकों के बारे में कुछ भी पता नहीं होता है प्रकाशित-सदस्यता प्रारूप के अन्य कार्यान्वयन जो इच्छुक पार्टियों को अधिसूचना और संचार के समान प्रभाव प्राप्त करते हैं पर्यवेक्षक प्रारूप का उपयोग नहीं करते हैं [3][4] ओएस/2 और माइक्रोसॉफ़्ट विंडोज़ जैसे मल्टी-विंडो संचालन प्रणाली के शुरुआती कार्यान्वयन में प्रकाशित-सदस्यता प्रारूप और घटना-संचालित सॉफ़्टवेयर विकास शब्द का उपयोग पर्यवेक्षक प्रारूप के पर्यायवाची के रूप में किया गया था [5] पर्यवेक्षक प्रारूप जैसा कि बनावट चिन्ह पुस्तक में वर्णित है एक बहुत ही बुनियादी अवधारणा है और पर्यवेक्षकों को सूचित करने से पहले या बाद में देखे गए विषय द्वारा किए जाने वाले विशेष तर्क या देखे गए विषय में परिवर्तनों में रुचि को हटाने का समाधान नहीं करता है यह प्रारूप परिवर्तन सूचनाओं को रिकॉर्ड करने या उनके प्राप्त होने की गारंटी देने से भी संबंधित नहीं है इन चिंताओं को आम तौर पर संदेश-कतार प्रणाली में नियंत्रित किया जाता है जिसमें पर्यवेक्षक प्रारूप केवल एक छोटा सा हिस्सा निभाता है।
संबंधित पैटर्न में प्रकाशित-सदस्यता मध्यस्थ प्रारूप और सिंगलटन प्रारूप सम्मिलित हैं।
अनयुग्मित
पर्यवेक्षक प्रारूप का उपयोग प्रकाशन-सदस्यता के अभाव में किया जा सकता है जैसे कि जब मॉडल स्थिति अधिकतर अद्यतन की जाती है बार-बार अद्यतन करने से दृश्य अनुत्तरदायी हो सकता है उदाहरण के लिए कई रंगाई के प्रारूप को लागू करके ऐसे पर्यवेक्षकों को इसके स्थान समय का उपयोग करना चाहिए तथा परिवर्तन संदेश द्वारा अतिभारित होने के जगह पर्यवेक्षक एक नियमित अंतराल पर मॉडल की अनुमानित स्थिति का प्रतिनिधित्व करने के लिए दृश्य का कारण बनेगा प्रेक्षक का यह मोड प्रगति पट्टी के लिए विशेष रूप से उपयोगी है जिसमें अंतर्निहित कार्यवाही की प्रगति बार-बार बदलती रहती है।
संरचना
यूएमएल वर्ग और अनुक्रम आरेख
इस एकीकृत मॉडलिंग भाषा वर्ग आरेख में वस्तु वर्ग निर्भर वस्तुओं की स्थिति को सीधे अद्यतन नहीं करता है केवल समस्या आपकी जानकारी के लिए है उन्मुख राज्य को अद्यतन करने के लिए जो बनाता है वस्तु निर्भर वस्तुओं की स्थिति को अद्यतन करने के तरीके से स्वतंत्र हैObserver1
ई> और Observer2
कक्षाएं कार्यान्वित करती हैं Observer
विषय की स्थिति के साथ हस्तक्षेप किया जाता है
एकीकृत मॉडलिंग भाषा अनुक्रम आरेख समय को परस्पर दिखाता है Observer1
ई> और Observer2
वस्तु को बुलाते हैं यह सम्पर्क पर Subject1
खुद को पंजीकृत करने के लिए यह मानते हुए कि स्थिति Subject1
परिवर्तन Subject1
कॉल notify()
अपने आप पर. notify()
कॉल update()
पंजीकृत पर Observer1
और Observer2 वस्तु
जो परिवर्तित डेटा का अनुरोध करते हैं (getState()
) से Subject1
उनकी स्थिति को अद्यतन करने के लिए।
यूएमएल वर्ग आरेख
उदाहरण
जबकि लाइब्रेरी कक्षाएं java.util.Observer
और java.util.Observable
मौजूद हैं, उन्हें जावा 9 में बहिष्कृत कर दिया गया है क्योंकि लागू किया गया मॉडल काफी सीमित था।
नीचे जावा (प्रोग्रामिंग भाषा) में लिखा गया एक उदाहरण है जो कीबोर्ड इनपुट लेता है और प्रत्येक इनपुट लाइन को एक इवेंट के रूप में संभालता है। जब एक स्ट्रिंग की आपूर्ति की जाती है System.in
, प्रक्रिया notifyObservers()
फिर घटना के घटित होने के बारे में सभी पर्यवेक्षकों को उनके अद्यतन तरीकों के आह्वान के रूप में सूचित करने के लिए बुलाया जाता है।
जावा
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;
interface Observer {
void update(String event);
}
class EventSource {
List<Observer> observers = new ArrayList<>();
void notifyObservers(String event) {
observers.forEach(observer -> observer.update(event));
}
void addObserver(Observer observer) {
observers.add(observer);
}
void scanSystemIn() {
var scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
notifyObservers(line);
}
}
}
public class ObserverDemo {
public static void main(String[] args) {
System.out.println("Enter Text : ");
var eventSource = new EventSource();
eventSource.addObserver(event -> System.out.println("Received response: " + event));
eventSource.scanSystemIn();
}
}
सी++
This is a C++11 implementation.
#include <functional>
#include <iostream>
#include <list>
class Subject; //Forward declaration for usage in Observer
class Observer
{
public:
explicit Observer(Subject& subj);
virtual ~Observer();
Observer(const Observer&) = delete; // rule of three
Observer& operator=(const Observer&) = delete;
virtual void update( Subject& s) const = 0;
private:
// Reference to a Subject object to detach in the destructor
Subject& subject;
};
// Subject is the base class for event generation
class Subject
{
public:
using RefObserver = std::reference_wrapper<const Observer>;
// Notify all the attached obsevers
void notify()
{
for (const auto& x: observers)
{
x.get().update(*this);
}
}
// Add an observer
void attach(const Observer& observer)
{
observers.push_front(observer);
}
// Remove an observer
void detach(Observer& observer)
{
observers.remove_if( [&observer ](const RefObserver& obj)
{
return &obj.get()==&observer;
});
}
private:
std::list<RefObserver> observers;
};
Observer::Observer(Subject& subj) : subject(subj)
{
subject.attach(*this);
}
Observer::~Observer()
{
subject.detach(*this);
}
// Example of usage
class ConcreteObserver: public Observer
{
public:
ConcreteObserver(Subject& subj) : Observer(subj) {}
// Get notification
void update(Subject&) const override
{
std::cout << "Got a notification" << std::endl;
}
};
int main()
{
Subject cs;
ConcreteObserver co1(cs);
ConcreteObserver co2(cs);
cs.notify();
}
The program output is like
Got a notification
Got a notification
ग्रूवी
class EventSource {
private observers = []
private notifyObservers(String event) {
observers.each { it(event) }
}
void addObserver(observer) {
observers += observer
}
void scanSystemIn() {
var scanner = new Scanner(System.in)
while (scanner) {
var line = scanner.nextLine()
notifyObservers(line)
}
}
}
println 'Enter Text: '
var eventSource = new EventSource()
eventSource.addObserver { event ->
println "Received response: $event"
}
eventSource.scanSystemIn()
कोटलिन
import java.util.Scanner
typealias Observer = (event: String) -> Unit;
class EventSource {
private var observers = mutableListOf<Observer>()
private fun notifyObservers(event: String) {
observers.forEach { it(event) }
}
fun addObserver(observer: Observer) {
observers += observer
}
fun scanSystemIn() {
val scanner = Scanner(System.`in`)
while (scanner.hasNext()) {
val line = scanner.nextLine()
notifyObservers(line)
}
}
}
fun main(arg: List<String>) {
println("Enter Text: ")
val eventSource = EventSource()
eventSource.addObserver { event ->
println("Received response: $event")
}
eventSource.scanSystemIn()
}
डेल्फ़ी
uses
System.Generics.Collections, System.SysUtils;
type
IObserver = interface
['{0C8F4C5D-1898-4F24-91DA-63F1DD66A692}']
procedure Update(const AValue: string);
end;
type
TObserverManager = class
private
FObservers: TList<IObserver>;
public
constructor Create; overload;
destructor Destroy; override;
procedure NotifyObservers(const AValue: string);
procedure AddObserver(const AObserver: IObserver);
procedure UnregisterObsrver(const AObserver: IObserver);
end;
type
TListener = class(TInterfacedObject, IObserver)
private
FName: string;
public
constructor Create(const AName: string); reintroduce;
procedure Update(const AValue: string);
end;
procedure TObserverManager.AddObserver(const AObserver: IObserver);
begin
if not FObservers.Contains(AObserver)
then FObservers.Add(AObserver);
end;
begin
FreeAndNil(FObservers);
inherited;
end;
procedure TObserverManager.NotifyObservers(const AValue: string);
var
i: Integer;
begin
for i := 0 to FObservers.Count - 1 do
FObservers[i].Update(AValue);
end;
procedure TObserverManager.UnregisterObsrver(const AObserver: IObserver);
begin
if FObservers.Contains(AObserver)
then FObservers.Remove(AObserver);
end;
constructor TListener.Create(const AName: string);
begin
inherited Create;
FName := AName;
end;
procedure TListener.Update(const AValue: string);
begin
WriteLn(FName + ' listener received notification: ' + AValue);
end;
procedure TMyForm.ObserverExampleButtonClick(Sender: TObject);
var
LDoorNotify: TObserverManager;
LListenerHusband: IObserver;
LListenerWife: IObserver;
begin
LDoorNotify := TObserverManager.Create;
try
LListenerHusband := TListener.Create('Husband');
LDoorNotify.AddObserver(LListenerHusband);
LListenerWife := TListener.Create('Wife');
LDoorNotify.AddObserver(LListenerWife);
LDoorNotify.NotifyObservers('Someone is knocking on the door');
finally
FreeAndNil(LDoorNotify);
end;
end;
उत्पादन <पूर्व> श्रोता पति को सूचना मिली कोई दरवाज़ा खटखटा रहा है तो श्रोता पत्नी को सूचना मिली: कोई दरवाज़ा खटखटा रहा है </पूर्व>
पायथन
Python_(प्रोग्रामिंग_भाषा) में एक समान उदाहरण
class Observable:
def __init__(self):
self._observers = []
def register_observer(self, observer):
self._observers.append(observer)
def notify_observers(self, *args, **kwargs):
for obs in self._observers:
obs.notify(self, *args, **kwargs)
class Observer:
def __init__(self, observable):
observable.register_observer(self)
def notify(self, observable, *args, **kwargs):
print("Got", args, kwargs, "From", observable)
subject = Observable()
observer = Observer(subject)
subject.notify_observers("test", kw="python")
# prints: Got ('test',) {'kw': 'python'} From <__main__.Observable object at 0x0000019757826FD0>
सी#
public class Payload
{
public string Message { get; set; }
}
public class Subject : IObservable<Payload>
{
public ICollection<IObserver<Payload>> Observers { get; set; }
public Subject()
{
Observers = new List<IObserver<Payload>>();
}
public IDisposable Subscribe(IObserver<Payload> observer)
{
if (!Observers.Contains(observer))
{
Observers.Add(observer);
}
return new Unsubscriber(observer, Observers);
}
public void SendMessage(string message)
{
foreach (var observer in Observers)
{
observer.OnNext(new Payload { Message = message });
}
}
}
public class Unsubscriber : IDisposable
{
private IObserver<Payload> observer;
private IList<IObserver<Payload>> observers;
public Unsubscriber(
IObserver<Payload> observer,
IList<IObserver<Payload>> observers)
{
this.observer = observer;
this.observers = observers;
}
public void Dispose()
{
if (observer != null && observers.Contains(observer))
{
observers.Remove(observer);
}
}
}
public class Observer : IObserver<Payload>
{
public string Message { get; set; }
public void OnCompleted()
{
}
public void OnError(Exception error)
{
}
public void OnNext(Payload value)
{
Message = value.Message;
}
public IDisposable Register(Subject subject)
{
return subject.Subscribe(this);
}
}
जावास्क्रिप्ट
जावास्क्रिप्ट को बहिष्कृत कर दिया गया है Object.observe
कार्यक्रम जो पर्यवेक्षक प्रारूप का अधिक कार्यान्वयन था [7] यह प्रेक्षित वस्तु में परिवर्तन होने पर घटनाओं को सक्रिय कर देगा पदावनत किये बिना Object.observe
फ़ंक्शन प्रारूप को अधिक स्पष्ट चिन्ह के साथ कार्यान्वित किया जा सकता है [8]
let Subject = {
_state: 0,
_observers: [],
add: function(observer) {
this._observers.push(observer);
},
getState: function() {
return this._state;
},
setState: function(value) {
this._state = value;
for (let i = 0; i < this._observers.length; i++)
{
this._observers[i].signal(this);
}
}
};
let Observer = {
signal: function(subject) {
let currentValue = subject.getState();
console.log(currentValue);
}
}
Subject.add(Observer);
Subject.setState(10);
//Output in console.log - 10
यह भी देखें
- निहित आह्वान।
- क्लाइंट-सर्वर मॉडल।
- पर्यवेक्षक पैटर्न का उपयोग अधिकतर इकाई-घटक प्रणाली प्रारूप में किया जाता है।
संदर्भ
- ↑ Erich Gamma; Richard Helm; Ralph Johnson; John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. pp. 293ff. ISBN 0-201-63361-2.
- ↑ "ऑब्जर्वर डिज़ाइन पैटर्न - समस्या, समाधान और प्रयोज्यता". w3sDesign.com. Retrieved 2017-08-12.
- ↑ Comparison between different observer pattern implementations Moshe Bindler, 2015 (Github)
- ↑ Differences between pub/sub and observer pattern The Observer Pattern by Adi Osmani (Safari books online)
- ↑ The Windows Programming Experience Charles Petzold, Nov 10, 1992, PC Magazine (Google Books)
- ↑ "ऑब्जर्वर डिज़ाइन पैटर्न - संरचना और सहयोग". w3sDesign.com. Retrieved 2017-08-12.
- ↑ "jQuery - Listening for variable changes in JavaScript".
- ↑ "Jquery - Listening for variable changes in JavaScript".
बाहरी संबंध
- Observer implementations in various languages at Wikibooks