Programing

Borg 패턴이 Python의 Singleton 패턴보다 나은 이유

crosscheck 2020. 10. 22. 07:40
반응형

Borg 패턴이 Python의 Singleton 패턴보다 나은 이유


Borg 패턴Singleton 패턴 보다 나은 이유는 무엇 입니까?

나는 그들이 다른 결과를 가져 오지 않기 때문에 묻는다.

보그 :

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()

여기에 표시하고 싶은 것은 Borg 또는 Singleton으로 구현 된 서비스 객체가 사소하지 않은 내부 상태를 가지고 있다는 것입니다 (이를 기반으로하는 일부 서비스를 제공합니다). 장난).

그리고이 상태는 초기화되어야합니다. 여기서 Singleton 구현은 더 간단합니다. init 를 전역 상태의 설정으로 취급 하기 때문입니다. Borg 개체가 자체적으로 업데이트해야하는지 확인하기 위해 내부 상태를 쿼리해야하는 것이 어색합니다.

내부 상태가 많을수록 악화됩니다. 예를 들어, 객체가 레지스터를 디스크에 저장하기 위해 응용 프로그램의 분해 신호를 수신해야하는 경우 해당 등록도 한 번만 수행해야하며 Singleton을 사용하면 더 쉽습니다.


보그가 다른 진짜 이유는 서브 클래 싱에 있습니다.

보그를 서브 클래 싱하면 해당 서브 클래스의 공유 상태를 명시 적으로 재정의하지 않는 한, 서브 클래스의 객체는 부모 클래스 객체와 동일한 상태를 갖습니다. 싱글 톤 패턴의 각 하위 클래스에는 자체 상태가 있으므로 다른 객체를 생성합니다.

또한 단일 패턴에서 객체는 상태뿐만 아니라 실제로 동일합니다 (상태가 실제로 중요한 유일한 것임에도 불구하고).


파이썬에서 어디에서나 접근 할 수있는 고유 한 "객체"를 원한다면 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

제 생각에는 Unique 구현이 가장 쉬우 며 Borg와 마지막으로 Singleton이 정의에 필요한 두 가지 기능이 있습니다.


그렇지 않습니다. 일반적으로 권장되지 않는 것은 파이썬에서 다음과 같은 패턴입니다.

class Singleton(object):

 _instance = None

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

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

생성자 대신 인스턴스를 가져 오기 위해 클래스 메서드를 사용합니다. Python의 메타 프로그래밍은 훨씬 더 나은 방법을 허용합니다. 예를 들어 Wikipedia에있는 방법 :

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()

클래스는 기본적으로 객체의 내부 상태에 액세스 (읽기 / 쓰기)하는 방법을 설명합니다.

In the singleton pattern you can only have a single class, i.e. all your objects will give you the same access points to the shared state. This means that if you have to provide an extended API, you will need to write a wrapper, wrapping around the singleton

In the borg pattern you are able to extend the base "borg" class, and thereby more conveniently extend the API for your taste.


It's only better in those few cases where you actually have a difference. Like when you subclass. The Borg pattern is extremely unusual, I've never needed it for real in ten years of Python programming.


Also, Borg-like pattern allows users of the class to choice if they want to share the state or create a separate instance. (whether or not this may be a good idea is a separate topic)

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 = ..

참고URL : https://stackoverflow.com/questions/1318406/why-is-the-borg-pattern-better-than-the-singleton-pattern-in-python

반응형