क्यों बोर्ग पैटर्न पायथन में सिंगलटन पैटर्न से बेहतर है


82

बोर्ग पैटर्न सिंगलटन पैटर्न से बेहतर क्यों है ?

मैं पूछता हूं क्योंकि मैं उन्हें अलग-अलग कुछ भी नहीं देखता हूं।

बोर्ग:

class Borg:
  __shared_state = {}
  # init internal state variables here
  __register = {}
  def __init__(self):
    self.__dict__ = self.__shared_state
    if not self.__register:
      self._init_default_register()

सिंगलटन:

class Singleton:
  def __init__(self):
    # init internal state variables here
    self.__register = {}
    self._init_default_register()

# singleton mechanics external to class, for example this in the module
Singleton = Singleton()

जो मैं यहां प्रदर्शित करना चाहता हूं वह यह है कि सेवा वस्तु, जिसे बोर्ग या सिंगलटन के रूप में लागू किया गया है, की एक आंतरिक आंतरिक स्थिति है (यह इसके आधार पर कुछ सेवा प्रदान करता है) (मेरा मतलब है कि यह कुछ उपयोगी होना चाहिए यह केवल एक सिंगलटन / बोर्ग के लिए नहीं है) आनंद)।

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

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


1
बोर्ग पैटर्न? ^ _ ^ मैंने पहली बार इसे c2.com/cgi/wiki?MonostatePattern
Jeffrey

9
मोनोस्टेट करें? हम मार्टेलिस हैं। हम बोर्ग कहते हैं।
u0b34a0f6ae

जवाबों:


66

बोर्ग अलग होने का असली कारण उपवर्ग में आता है।

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

सिंगलटन पैटर्न में भी वस्तुएं वास्तव में एक ही हैं, न केवल राज्य (भले ही राज्य केवल एक चीज है जो वास्तव में मायने रखता है)।


1
> सिंगलटन पैटर्न में भी वस्तुएं वास्तव में एक ही हैं, न कि केवल राज्य (भले ही राज्य केवल एक चीज है जो वास्तव में मायने रखता है)। वह बुरी चीज क्यों है?
agiliq

अच्छा सवाल uswaretech, यह ऊपर मेरे सवाल का एक हिस्सा है। जो बुरा कहा जाता है वह क्या है?
u0b34a0f6ae

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

फिर Noneअजगर में कैसे एक सिंगलटन है और बोर्ग पैटर्न का उदाहरण नहीं है?
चांग झाओ

@ चांगझाओ: क्योंकि किसी के मामले में हमें समान पहचान की आवश्यकता है, न कि केवल साझा राज्य। हम x is Noneचेकिंग करते हैं । इसके अलावा, कोई भी एक विशेष मामला नहीं है क्योंकि हम किसी के उपवर्ग नहीं बना सकते हैं।
जैतून '’

23

अजगर में यदि आप एक अद्वितीय "वस्तु" चाहते हैं जिसे आप कहीं से भी एक्सेस कर सकते हैं तो एक वर्ग बनाएं Uniqueजिसमें केवल स्थिर विशेषताएँ हों, @staticmethods और @classmethods; आप इसे यूनिक पैटर्न कह सकते हैं। यहां मैं 3 पैटर्न लागू करता हूं और तुलना करता हूं:

अद्वितीय

#Unique Pattern
class Unique:
#Define some static variables here
    x = 1
    @classmethod
    def init(cls):
        #Define any computation performed when assigning to a "new" object
        return cls

एकाकी वस्तु

#Singleton Pattern
class Singleton:

    __single = None 

    def __init__(self):
        if not Singleton.__single:
            #Your definitions here
            self.x = 1 
        else:
            raise RuntimeError('A Singleton already exists') 

    @classmethod
    def getInstance(cls):
        if not cls.__single:
            cls.__single = Singleton()
        return cls.__single

बोर्ग

#Borg Pattern
class Borg:

    __monostate = None

    def __init__(self):
        if not Borg.__monostate:
            Borg.__monostate = self.__dict__
            #Your definitions here
            self.x = 1

        else:
            self.__dict__ = Borg.__monostate

परीक्षा

#SINGLETON
print "\nSINGLETON\n"
A = Singleton.getInstance()
B = Singleton.getInstance()

print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "After A.x = 2"
print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)
print  "Are A and B the same object? Answer: {}".format(id(A)==id(B))


#BORG
print "\nBORG\n"
A = Borg()
B = Borg()

print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "After A.x = 2"
print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)
print  "Are A and B the same object? Answer: {}".format(id(A)==id(B))


#UNIQUE
print "\nUNIQUE\n"
A = Unique.init()
B = Unique.init()

print "At first B.x = {} and A.x = {}".format(B.x,A.x)
A.x = 2
print "After A.x = 2"
print "Now both B.x = {} and A.x = {}\n".format(B.x,A.x)
print  "Are A and B the same object? Answer: {}".format(id(A)==id(B))

आउटपुट:

एकाकी वस्तु

At first B.x = 1 and A.x = 1
After A.x = 2
Now both B.x = 2 and A.x = 2

Are A and B the same object? Answer: True

BORG

At first B.x = 1 and A.x = 1
After A.x = 2
Now both B.x = 2 and A.x = 2

Are A and B the same object? Answer: False

UNIQUE

At first B.x = 1 and A.x = 1
After A.x = 2
Now both B.x = 2 and A.x = 2

Are A and B the same object? Answer: True

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


14

यह नहीं। अजगर में इस तरह एक पैटर्न आमतौर पर अनुशंसित नहीं है:

class Singleton(object):

 _instance = None

 def __init__(self, ...):
  ...

 @classmethod
 def instance(cls):
  if cls._instance is None:
   cls._instance = cls(...)
  return cls._instance

जहां आप कंस्ट्रक्टर के बजाय इंस्टेंस प्राप्त करने के लिए क्लास विधि का उपयोग करते हैं। पायथन के metaprogramming की अनुमति देता है ज्यादा बेहतर तरीके, पर एक जैसे विकिपीडिया :

class Singleton(type):
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)
        cls.instance = None

    def __call__(cls, *args, **kw):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kw)

        return cls.instance

class MyClass(object):
    __metaclass__ = Singleton

print MyClass()
print MyClass()

+1 मोनोस्टेट (Borg) पैटर्न सिंगलटन से भी बदतर है (हाँ, यह संभव है) क्योंकि निजी a = new Borg (); निजी b = नया बोर्ग (); b.mutate (); और एक बदल गया है! कितना भ्रामक है?
माइकल डियरडफ

5
सबसे अच्छा / बुरा? यह आपके usecase पर निर्भर करेगा यह नहीं होगा। मैं कई मामलों के बारे में सोच सकता हूं जहां आप चाहते हैं कि राज्य इस तरह संरक्षित हो।
रिकाए

5
यह कोई समस्या नहीं है, @MichaelDeardeuff। यह अभिप्रेत व्यवहार है । उन्हें समान होना चाहिए। Borg पैटर्न में एक समस्या IMHO है, कि अगर आप Borg .__ init__ मेथड में कुछ इनिशियलाइज़िंग वैरिएबल जोड़ते हैं, जैसे self.text = "", तो उस ऑब्जेक्ट को चेंज करें borg1.text = "blah"और फिर एक नई ऑब्जेक्ट `borg2 = Borg ()" - wham! सभी borg1 विशेषताएँ उस पर क्लिक करें! में प्रारंभ कर रहे हैं init । whiped कर रहे हैं ताकि instantiating असंभव है - या बेहतर: बोर्ग पैटर्न में, आप नहीं कर सकते हैं इनिशियलाइज़ सदस्य में जिम्मेदार बताते हैं init विधि!
nerdoc

यह एक सिंगलटन में संभव है क्योंकि एक ifचेक वेदर है जो पहले से ही एक उदाहरण है, और यदि हाँ, तो यह केवल ओवरराइडिंग इनिशियलाइज़ेशन के बिना लौटा है!
nerdoc

वही बोर्ग इनिट में किया जा सकता है (और होना चाहिए) । if __monostate: returnऔर उसके बाद अपना स्वयं करें। foo = 'bar'
volodymyr

8

एक वर्ग मूल रूप से वर्णन करता है कि आप अपनी वस्तु की आंतरिक स्थिति तक (पढ़ / लिख) कैसे सकते हैं।

सिंगलटन पैटर्न में आपके पास केवल एक एकल वर्ग हो सकता है, अर्थात आपकी सभी वस्तुएं आपको साझा राज्य तक समान पहुंच बिंदु प्रदान करेंगी। इसका मतलब है कि यदि आपको एक विस्तारित एपीआई प्रदान करना है, तो आपको सिंगलटन के चारों ओर लपेटते हुए, एक आवरण लिखना होगा

बोर्ग पैटर्न में आप आधार "बोर्ग" वर्ग का विस्तार करने में सक्षम हैं, और इस तरह से अधिक आसानी से अपने स्वाद के लिए एपीआई का विस्तार कर सकते हैं।


8

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


2

इसके अलावा, बोर्ग जैसा पैटर्न वर्ग के उपयोगकर्ताओं को पसंद करने की अनुमति देता है यदि वे राज्य को साझा करना चाहते हैं या एक अलग उदाहरण बनाना चाहते हैं। (यह एक अच्छा विचार हो सकता है या नहीं यह एक अलग विषय है)

class MayBeBorg:
    __monostate = None

    def __init__(self, shared_state=True, ..):
        if shared_state:

            if not MayBeBorg.__monostate:
                MayBeBorg.__monostate = self.__dict__
            else:
                self.__dict__ = MayBeBorg.__monostate
                return
        self.wings = ..
        self.beak = ..
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.